From 955a2e7e18c895d1b2580fcc9ef3d955c5d435a1 Mon Sep 17 00:00:00 2001 From: Grzegorz Piwowarek Date: Sat, 27 Jan 2018 06:52:34 +0100 Subject: [PATCH 01/28] Reactive exception handling --- .../websocket/ReactiveWebSocketHandler.java | 45 ++++++++----------- 1 file changed, 19 insertions(+), 26 deletions(-) diff --git a/spring-5-reactive/src/main/java/com/baeldung/reactive/websocket/ReactiveWebSocketHandler.java b/spring-5-reactive/src/main/java/com/baeldung/reactive/websocket/ReactiveWebSocketHandler.java index 669c212fd3..2e93c0c0dc 100644 --- a/spring-5-reactive/src/main/java/com/baeldung/reactive/websocket/ReactiveWebSocketHandler.java +++ b/spring-5-reactive/src/main/java/com/baeldung/reactive/websocket/ReactiveWebSocketHandler.java @@ -1,48 +1,41 @@ package com.baeldung.reactive.websocket; -import org.springframework.web.reactive.socket.WebSocketSession; - import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; - import org.springframework.stereotype.Component; import org.springframework.web.reactive.socket.WebSocketHandler; import org.springframework.web.reactive.socket.WebSocketMessage; - +import org.springframework.web.reactive.socket.WebSocketSession; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; import java.time.Duration; -import java.time.LocalDateTime; -import java.util.UUID; + +import static java.time.LocalDateTime.now; +import static java.util.UUID.randomUUID; @Component public class ReactiveWebSocketHandler implements WebSocketHandler { - private Flux eventFlux = Flux.generate(e -> { - Event event = new Event(UUID.randomUUID().toString(), LocalDateTime.now().toString()); - e.next(event); + private static final ObjectMapper json = new ObjectMapper(); + + private Flux eventFlux = Flux.generate(sink -> { + Event event = new Event(randomUUID().toString(), now().toString()); + try { + sink.next(json.writeValueAsString(event)); + } catch (JsonProcessingException e) { + sink.error(e); + } }); - private Flux intervalFlux = Flux.interval(Duration.ofMillis(1000L)).zipWith(eventFlux, (time, event) -> event); - - private ObjectMapper json = new ObjectMapper(); + private Flux intervalFlux = Flux.interval(Duration.ofMillis(1000L)) + .zipWith(eventFlux, (time, event) -> event); @Override public Mono handle(WebSocketSession webSocketSession) { - - return webSocketSession.send(intervalFlux.map(event -> { - try { - String jsonEvent = json.writeValueAsString(event); - System.out.println(jsonEvent); - return jsonEvent; - } catch (JsonProcessingException e) { - e.printStackTrace(); - return ""; - } - }).map(webSocketSession::textMessage)) - - .and(webSocketSession.receive().map(WebSocketMessage::getPayloadAsText).log()); + return webSocketSession.send(intervalFlux + .map(webSocketSession::textMessage)) + .and(webSocketSession.receive() + .map(WebSocketMessage::getPayloadAsText).log()); } - } From 4d8f0a48ae285bd681758f5da5ab785fa91b6fa1 Mon Sep 17 00:00:00 2001 From: k0l0ssus Date: Sun, 28 Jan 2018 18:06:11 -0500 Subject: [PATCH 02/28] Add Java vs Vavr Stream sample --- .../samples/java/vavr/VavrSampler.java | 99 +++++++++++++++++++ 1 file changed, 99 insertions(+) create mode 100644 vavr/src/main/java/com/baeldung/samples/java/vavr/VavrSampler.java diff --git a/vavr/src/main/java/com/baeldung/samples/java/vavr/VavrSampler.java b/vavr/src/main/java/com/baeldung/samples/java/vavr/VavrSampler.java new file mode 100644 index 0000000000..ae06c97e2e --- /dev/null +++ b/vavr/src/main/java/com/baeldung/samples/java/vavr/VavrSampler.java @@ -0,0 +1,99 @@ +package com.baeldung.samples.java.vavr; + +import io.vavr.collection.Stream; +import java.util.ArrayList; +import java.util.List; + + +/** + * + * @author baeldung + */ +public class VavrSampler { + + static int[] intArray = new int[]{1, 2, 4}; + static List intList = new ArrayList(); + static int[][] intOfInts = new int[][]{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; + + public static void main(String[] args) { + vavrStreamElementAccess(); + System.out.println("===================================="); + vavrParallelStreamAccess(); + System.out.println("===================================="); + vavrFlatMapping(); + System.out.println("===================================="); + vavrStreamManipulation(); + System.out.println("===================================="); + vavrStreamDistinct(); + } + + public static void vavrStreamElementAccess() { + System.out.println("Vavr Element Access"); + System.out.println("===================================="); + Stream vavredStream = Stream.ofAll(intArray); + System.out.println("Vavr index access: " + vavredStream.get(2)); + System.out.println("Vavr head element access: " + vavredStream.get()); + + Stream vavredStringStream = Stream.of("foo", "bar", "baz"); + System.out.println("Find foo " + vavredStringStream.indexOf("foo")); + } + + public static void vavrParallelStreamAccess() { + + System.out.println("Vavr Stream Concurrent Modification"); + System.out.println("===================================="); + Stream vavrStream = Stream.ofAll(intList); + //intList.add(5); + vavrStream.forEach(i -> System.out.println("in a Vavr Stream: " + i)); + +// Stream wrapped = Stream.ofAll(intArray); +// intArray[2] = 5; +// wrapped.forEach(i -> System.out.println("Vavr looped " + i)); + } + + public static void jdkFlatMapping() { + System.out.println("Java flatMapping"); + System.out.println("===================================="); + java.util.stream.Stream.of(42).flatMap(i -> java.util.stream.Stream.generate(() -> { + System.out.println("nested call"); + return 42; + })).findAny(); + } + + public static void vavrFlatMapping() { + System.out.println("Vavr flatMapping"); + System.out.println("===================================="); + Stream.of(42) + .flatMap(i -> Stream.continually(() -> { + System.out.println("nested call"); + return 42; + })) + .get(0); + } + + public static void vavrStreamManipulation() { + System.out.println("Vavr Stream Manipulation"); + System.out.println("===================================="); + List stringList = new ArrayList<>(); + stringList.add("foo"); + stringList.add("bar"); + stringList.add("baz"); + Stream vavredStream = Stream.ofAll(stringList); + vavredStream.forEach(item -> System.out.println("Vavr Stream item: " + item)); + Stream vavredStream2 = vavredStream.insert(2, "buzz"); + vavredStream2.forEach(item -> System.out.println("Vavr Stream item after stream addition: " + item)); + stringList.forEach(item -> System.out.println("List item after stream addition: " + item)); + Stream deletionStream = vavredStream.remove("bar"); + deletionStream.forEach(item -> System.out.println("Vavr Stream item after stream item deletion: " + item)); + + } + + public static void vavrStreamDistinct() { + Stream vavredStream = Stream.of("foo", "bar", "baz", "buxx", "bar", "bar", "foo"); + Stream distinctVavrStream = vavredStream.distinctBy((y, z) -> { + return y.compareTo(z); + }); + distinctVavrStream.forEach(item -> System.out.println("Vavr Stream item after distinct query " + item)); + + } +} From f888a3f78accaa6588f36528b8eee5a8c27772bc Mon Sep 17 00:00:00 2001 From: Bogdan Stoean <4540392+BogdanStoean@users.noreply.github.com> Date: Mon, 29 Jan 2018 07:44:40 +0200 Subject: [PATCH 03/28] BAEL-1410 - refactor tests (#3525) * initial setup with spring boot/ spring data jpa/ flyway * BAEL-1315 - added flyway test extensions for spring * BAEL-1315 - added flyway test extensions for spring * BAEL-1315 - created multiple migration scripts and locations * BAEL-1315 - test insert after schema creation * cleanup * BAEL-1315 - test data changes by a migration * [BAEL-1410] Spring Boot Security Auto-Configuration * [BAEL-1410] Added some tests for incorrect credentials use case * [BAEL-1410] Added readme and some code improvements * [BAEL-1410] removed form based auth config because is redundant added oauth2 server auto-configuration sample with test * [BAEL-1410] added custom Authorization Server Config * [BAEL-1410] update README * [BAEL-1410]refactor tests * [BAEL-1410]oauth2 resource server * [BAEL-1410]oauth2 sso sample with facebook * [BAEL-1410]remove spring-flyway * [BAEL-1410]refactor tests * [BAEL-1410] refactor tests * [BAEL-1410] update --- ...BasicAuthConfigurationIntegrationTest.java | 2 + ...figAuthorizationServerIntegrationTest.java | 55 ++++++------------- ...figAuthorizationServerIntegrationTest.java | 26 +++------ .../OAuth2IntegrationTestSupport.java | 34 ++++++++++++ 4 files changed, 59 insertions(+), 58 deletions(-) create mode 100644 spring-boot-security/src/test/java/com/baeldung/springbootsecurity/oauth2server/OAuth2IntegrationTestSupport.java diff --git a/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/basic_auth/BasicAuthConfigurationIntegrationTest.java b/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/basic_auth/BasicAuthConfigurationIntegrationTest.java index 4e4244abb7..32c3fbdef4 100644 --- a/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/basic_auth/BasicAuthConfigurationIntegrationTest.java +++ b/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/basic_auth/BasicAuthConfigurationIntegrationTest.java @@ -37,6 +37,7 @@ public class BasicAuthConfigurationIntegrationTest { @Test public void whenLoggedUserRequestsHomePage_ThenSuccess() throws IllegalStateException, IOException { ResponseEntity response = restTemplate.getForEntity(base.toString(), String.class); + assertEquals(HttpStatus.OK, response.getStatusCode()); assertTrue(response .getBody() @@ -47,6 +48,7 @@ public class BasicAuthConfigurationIntegrationTest { public void whenUserWithWrongCredentialsRequestsHomePage_ThenUnauthorizedPage() throws IllegalStateException, IOException { restTemplate = new TestRestTemplate("user", "wrongpassword"); ResponseEntity response = restTemplate.getForEntity(base.toString(), String.class); + assertEquals(HttpStatus.UNAUTHORIZED, response.getStatusCode()); assertTrue(response .getBody() diff --git a/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/oauth2server/CustomConfigAuthorizationServerIntegrationTest.java b/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/oauth2server/CustomConfigAuthorizationServerIntegrationTest.java index 09df9ce645..cc953eef5a 100644 --- a/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/oauth2server/CustomConfigAuthorizationServerIntegrationTest.java +++ b/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/oauth2server/CustomConfigAuthorizationServerIntegrationTest.java @@ -2,10 +2,7 @@ package com.baeldung.springbootsecurity.oauth2server; import org.junit.Test; import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; -import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext; import org.springframework.security.oauth2.client.OAuth2RestTemplate; import org.springframework.security.oauth2.client.resource.OAuth2AccessDeniedException; import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails; @@ -13,7 +10,6 @@ import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.test.context.ActiveProfiles; import org.springframework.test.context.junit4.SpringRunner; -import static java.lang.String.format; import static java.util.Collections.singletonList; import static org.junit.Assert.assertNotNull; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; @@ -21,54 +17,35 @@ import static org.springframework.boot.test.context.SpringBootTest.WebEnvironmen @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = RANDOM_PORT, classes = SpringBootAuthorizationServerApplication.class) @ActiveProfiles("authz") -public class CustomConfigAuthorizationServerIntegrationTest { - - @Value("${local.server.port}") protected int port; +public class CustomConfigAuthorizationServerIntegrationTest extends OAuth2IntegrationTestSupport { @Test - public void whenAccessTokenIsRequested_ThenAccessTokenValueIsNotNull() { - ClientCredentialsResourceDetails resourceDetails = getClientCredentialsResourceDetails(); - resourceDetails.setClientId("baeldung"); - resourceDetails.setClientSecret("baeldung"); - resourceDetails.setScope(singletonList("read")); - DefaultOAuth2ClientContext clientContext = new DefaultOAuth2ClientContext(); - OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails, clientContext); - restTemplate.setMessageConverters(singletonList(new MappingJackson2HttpMessageConverter())); + public void givenOAuth2Context_whenAccessTokenIsRequested_ThenAccessTokenValueIsNotNull() { + ClientCredentialsResourceDetails resourceDetails = getClientCredentialsResourceDetails("baeldung", singletonList("read")); + OAuth2RestTemplate restTemplate = getOAuth2RestTemplate(resourceDetails); + OAuth2AccessToken accessToken = restTemplate.getAccessToken(); + assertNotNull(accessToken); } @Test(expected = OAuth2AccessDeniedException.class) - public void whenAccessTokenIsRequestedWithInvalidException_ThenExceptionIsThrown() { - ClientCredentialsResourceDetails resourceDetails = getClientCredentialsResourceDetails(); - resourceDetails.setClientId("baeldung"); - resourceDetails.setClientSecret("baeldung"); - resourceDetails.setScope(singletonList("write")); - DefaultOAuth2ClientContext clientContext = new DefaultOAuth2ClientContext(); - OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails, clientContext); - restTemplate.setMessageConverters(singletonList(new MappingJackson2HttpMessageConverter())); + public void givenOAuth2Context_whenAccessTokenIsRequestedWithInvalidException_ThenExceptionIsThrown() { + ClientCredentialsResourceDetails resourceDetails = getClientCredentialsResourceDetails("baeldung", singletonList("write")); + OAuth2RestTemplate restTemplate = getOAuth2RestTemplate(resourceDetails); + restTemplate.getAccessToken(); } @Test - public void whenAccessTokenIsRequestedByClientWithWriteScope_ThenAccessTokenIsNotNull() { - ClientCredentialsResourceDetails resourceDetails = getClientCredentialsResourceDetails(); - resourceDetails.setClientId("baeldung-admin"); - resourceDetails.setClientSecret("baeldung"); - resourceDetails.setScope(singletonList("write")); - DefaultOAuth2ClientContext clientContext = new DefaultOAuth2ClientContext(); - OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails, clientContext); - restTemplate.setMessageConverters(singletonList(new MappingJackson2HttpMessageConverter())); - OAuth2AccessToken accessToken = restTemplate.getAccessToken(); - assertNotNull(accessToken); - } + public void givenOAuth2Context_whenAccessTokenIsRequestedByClientWithWriteScope_ThenAccessTokenIsNotNull() { + ClientCredentialsResourceDetails resourceDetails = getClientCredentialsResourceDetails("baeldung-admin", singletonList("write")); + OAuth2RestTemplate restTemplate = getOAuth2RestTemplate(resourceDetails); - private ClientCredentialsResourceDetails getClientCredentialsResourceDetails() { - ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails(); - resourceDetails.setAccessTokenUri(format("http://localhost:%d/oauth/token", port)); - resourceDetails.setGrantType("client_credentials"); - return resourceDetails; + OAuth2AccessToken accessToken = restTemplate.getAccessToken(); + + assertNotNull(accessToken); } } diff --git a/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/oauth2server/DefaultConfigAuthorizationServerIntegrationTest.java b/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/oauth2server/DefaultConfigAuthorizationServerIntegrationTest.java index c7b1b4ef6c..4d7b449380 100644 --- a/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/oauth2server/DefaultConfigAuthorizationServerIntegrationTest.java +++ b/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/oauth2server/DefaultConfigAuthorizationServerIntegrationTest.java @@ -2,40 +2,28 @@ package com.baeldung.springbootsecurity.oauth2server; import org.junit.Test; import org.junit.runner.RunWith; -import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.context.SpringBootTest; -import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; -import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext; import org.springframework.security.oauth2.client.OAuth2RestTemplate; import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails; import org.springframework.security.oauth2.common.OAuth2AccessToken; import org.springframework.test.context.junit4.SpringRunner; -import static java.lang.String.format; import static java.util.Arrays.asList; -import static java.util.Collections.singletonList; import static org.junit.Assert.assertNotNull; import static org.springframework.boot.test.context.SpringBootTest.WebEnvironment.RANDOM_PORT; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = RANDOM_PORT, classes = SpringBootAuthorizationServerApplication.class, - properties = { "security.oauth2.client.client-id=client", "security.oauth2.client.client-secret=secret" }) -public class DefaultConfigAuthorizationServerIntegrationTest { - - @Value("${local.server.port}") protected int port; + properties = { "security.oauth2.client.client-id=client", "security.oauth2.client.client-secret=baeldung" }) +public class DefaultConfigAuthorizationServerIntegrationTest extends OAuth2IntegrationTestSupport { @Test - public void whenAccessTokenIsRequested_ThenAccessTokenValueIsNotNull() { - ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails(); - resourceDetails.setAccessTokenUri(format("http://localhost:%d/oauth/token", port)); - resourceDetails.setClientId("client"); - resourceDetails.setClientSecret("secret"); - resourceDetails.setGrantType("client_credentials"); - resourceDetails.setScope(asList("read", "write")); - DefaultOAuth2ClientContext clientContext = new DefaultOAuth2ClientContext(); - OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails, clientContext); - restTemplate.setMessageConverters(singletonList(new MappingJackson2HttpMessageConverter())); + public void givenOAuth2Context_whenAccessTokenIsRequested_ThenAccessTokenValueIsNotNull() { + ClientCredentialsResourceDetails resourceDetails = getClientCredentialsResourceDetails("client", asList("read", "write")); + OAuth2RestTemplate restTemplate = getOAuth2RestTemplate(resourceDetails); + OAuth2AccessToken accessToken = restTemplate.getAccessToken(); + assertNotNull(accessToken); } diff --git a/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/oauth2server/OAuth2IntegrationTestSupport.java b/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/oauth2server/OAuth2IntegrationTestSupport.java new file mode 100644 index 0000000000..3eef206c7d --- /dev/null +++ b/spring-boot-security/src/test/java/com/baeldung/springbootsecurity/oauth2server/OAuth2IntegrationTestSupport.java @@ -0,0 +1,34 @@ +package com.baeldung.springbootsecurity.oauth2server; + +import org.springframework.beans.factory.annotation.Value; +import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter; +import org.springframework.security.oauth2.client.DefaultOAuth2ClientContext; +import org.springframework.security.oauth2.client.OAuth2RestTemplate; +import org.springframework.security.oauth2.client.token.grant.client.ClientCredentialsResourceDetails; + +import java.util.List; + +import static java.lang.String.format; +import static java.util.Collections.singletonList; + +public class OAuth2IntegrationTestSupport { + + @Value("${local.server.port}") protected int port; + + protected ClientCredentialsResourceDetails getClientCredentialsResourceDetails(final String clientId, final List scopes) { + ClientCredentialsResourceDetails resourceDetails = new ClientCredentialsResourceDetails(); + resourceDetails.setAccessTokenUri(format("http://localhost:%d/oauth/token", port)); + resourceDetails.setClientId(clientId); + resourceDetails.setClientSecret("baeldung"); + resourceDetails.setScope(scopes); + resourceDetails.setGrantType("client_credentials"); + return resourceDetails; + } + + protected OAuth2RestTemplate getOAuth2RestTemplate(final ClientCredentialsResourceDetails resourceDetails) { + DefaultOAuth2ClientContext clientContext = new DefaultOAuth2ClientContext(); + OAuth2RestTemplate restTemplate = new OAuth2RestTemplate(resourceDetails, clientContext); + restTemplate.setMessageConverters(singletonList(new MappingJackson2HttpMessageConverter())); + return restTemplate; + } +} From b070f3ddaa207a66101a5ea1e51ad4e52854ae97 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Carsten=20Gr=C3=A4f?= Date: Mon, 29 Jan 2018 07:37:17 +0100 Subject: [PATCH 04/28] fixed formatting --- .../samples/java/vavr/VavrSampler.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/vavr/src/main/java/com/baeldung/samples/java/vavr/VavrSampler.java b/vavr/src/main/java/com/baeldung/samples/java/vavr/VavrSampler.java index ae06c97e2e..f4e0728f32 100644 --- a/vavr/src/main/java/com/baeldung/samples/java/vavr/VavrSampler.java +++ b/vavr/src/main/java/com/baeldung/samples/java/vavr/VavrSampler.java @@ -1,9 +1,9 @@ package com.baeldung.samples.java.vavr; -import io.vavr.collection.Stream; import java.util.ArrayList; import java.util.List; +import io.vavr.collection.Stream; /** * @@ -11,12 +11,12 @@ import java.util.List; */ public class VavrSampler { - static int[] intArray = new int[]{1, 2, 4}; - static List intList = new ArrayList(); - static int[][] intOfInts = new int[][]{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}}; + static int[] intArray = new int[] { 1, 2, 4 }; + static List intList = new ArrayList<>(); + static int[][] intOfInts = new int[][] { { 1, 2, 3 }, { 4, 5, 6 }, { 7, 8, 9 } }; public static void main(String[] args) { - vavrStreamElementAccess(); + vavrStreamElementAccess(); System.out.println("===================================="); vavrParallelStreamAccess(); System.out.println("===================================="); @@ -43,12 +43,12 @@ public class VavrSampler { System.out.println("Vavr Stream Concurrent Modification"); System.out.println("===================================="); Stream vavrStream = Stream.ofAll(intList); - //intList.add(5); + // intList.add(5); vavrStream.forEach(i -> System.out.println("in a Vavr Stream: " + i)); -// Stream wrapped = Stream.ofAll(intArray); -// intArray[2] = 5; -// wrapped.forEach(i -> System.out.println("Vavr looped " + i)); + // Stream wrapped = Stream.ofAll(intArray); + // intArray[2] = 5; + // wrapped.forEach(i -> System.out.println("Vavr looped " + i)); } public static void jdkFlatMapping() { @@ -65,9 +65,9 @@ public class VavrSampler { System.out.println("===================================="); Stream.of(42) .flatMap(i -> Stream.continually(() -> { - System.out.println("nested call"); - return 42; - })) + System.out.println("nested call"); + return 42; + })) .get(0); } From d1a4848cb49bbf4ec6fe720fea109f715be53779 Mon Sep 17 00:00:00 2001 From: Aprian Diaz Novandi Date: Mon, 29 Jan 2018 09:26:15 +0100 Subject: [PATCH 05/28] BAEL-1464 Guava Memoizer (#3420) * BAEL-1464 Guava Memoizer * Update codes based on code review and discussion in JIRA --- .../guava/memoizer/CostlySupplier.java | 17 ++++ .../baeldung/guava/memoizer/Factorial.java | 22 +++++ .../guava/memoizer/FibonacciSequence.java | 26 +++++ .../baeldung/guava/GuavaMemoizerUnitTest.java | 98 +++++++++++++++++++ 4 files changed, 163 insertions(+) create mode 100644 guava/src/main/java/org/baeldung/guava/memoizer/CostlySupplier.java create mode 100644 guava/src/main/java/org/baeldung/guava/memoizer/Factorial.java create mode 100644 guava/src/main/java/org/baeldung/guava/memoizer/FibonacciSequence.java create mode 100644 guava/src/test/java/org/baeldung/guava/GuavaMemoizerUnitTest.java diff --git a/guava/src/main/java/org/baeldung/guava/memoizer/CostlySupplier.java b/guava/src/main/java/org/baeldung/guava/memoizer/CostlySupplier.java new file mode 100644 index 0000000000..63b3fbd438 --- /dev/null +++ b/guava/src/main/java/org/baeldung/guava/memoizer/CostlySupplier.java @@ -0,0 +1,17 @@ +package org.baeldung.guava.memoizer; + +import java.math.BigInteger; +import java.util.Random; +import java.util.concurrent.TimeUnit; + +public class CostlySupplier { + + public static BigInteger generateBigNumber() { + try { + TimeUnit.SECONDS.sleep(2); + } catch (InterruptedException e) { + } + return new BigInteger("12345"); + } + +} diff --git a/guava/src/main/java/org/baeldung/guava/memoizer/Factorial.java b/guava/src/main/java/org/baeldung/guava/memoizer/Factorial.java new file mode 100644 index 0000000000..74fcbdcc14 --- /dev/null +++ b/guava/src/main/java/org/baeldung/guava/memoizer/Factorial.java @@ -0,0 +1,22 @@ +package org.baeldung.guava.memoizer; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; + +import java.math.BigInteger; + +public class Factorial { + + private static LoadingCache memo = CacheBuilder.newBuilder() + .build(CacheLoader.from(Factorial::getFactorial)); + + public static BigInteger getFactorial(int n) { + if (n == 0) { + return BigInteger.ONE; + } else { + return BigInteger.valueOf(n).multiply(memo.getUnchecked(n - 1)); + } + } + +} diff --git a/guava/src/main/java/org/baeldung/guava/memoizer/FibonacciSequence.java b/guava/src/main/java/org/baeldung/guava/memoizer/FibonacciSequence.java new file mode 100644 index 0000000000..0c70f08c23 --- /dev/null +++ b/guava/src/main/java/org/baeldung/guava/memoizer/FibonacciSequence.java @@ -0,0 +1,26 @@ +package org.baeldung.guava.memoizer; + +import com.google.common.cache.CacheBuilder; +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; + +import java.math.BigInteger; +import java.util.concurrent.TimeUnit; + +public class FibonacciSequence { + + private static LoadingCache memo = CacheBuilder.newBuilder() + .maximumSize(100) + .build(CacheLoader.from(FibonacciSequence::getFibonacciNumber)); + + public static BigInteger getFibonacciNumber(int n) { + if (n == 0) { + return BigInteger.ZERO; + } else if (n == 1) { + return BigInteger.ONE; + } else { + return memo.getUnchecked(n - 1).add(memo.getUnchecked(n - 2)); + } + } + +} diff --git a/guava/src/test/java/org/baeldung/guava/GuavaMemoizerUnitTest.java b/guava/src/test/java/org/baeldung/guava/GuavaMemoizerUnitTest.java new file mode 100644 index 0000000000..0ae1f438e3 --- /dev/null +++ b/guava/src/test/java/org/baeldung/guava/GuavaMemoizerUnitTest.java @@ -0,0 +1,98 @@ +package org.baeldung.guava; + +import com.google.common.base.Suppliers; +import org.baeldung.guava.memoizer.CostlySupplier; +import org.baeldung.guava.memoizer.Factorial; +import org.baeldung.guava.memoizer.FibonacciSequence; +import org.junit.Test; + +import java.math.BigInteger; +import java.time.Duration; +import java.time.Instant; +import java.util.concurrent.TimeUnit; +import java.util.function.Supplier; + +import static org.hamcrest.core.Is.is; +import static org.hamcrest.core.IsEqual.equalTo; +import static org.hamcrest.number.IsCloseTo.closeTo; +import static org.junit.Assert.assertThat; + +public class GuavaMemoizerUnitTest { + + @Test + public void givenInteger_whenGetFibonacciNumber_thenShouldCalculateFibonacciNumber() { + // given + int n = 95; + + // when + BigInteger fibonacciNumber = FibonacciSequence.getFibonacciNumber(n); + + // then + BigInteger expectedFibonacciNumber = new BigInteger("31940434634990099905"); + assertThat(fibonacciNumber, is(equalTo(expectedFibonacciNumber))); + } + + @Test + public void givenInteger_whenGetFactorial_thenShouldCalculateFactorial() { + // given + int n = 95; + + // when + BigInteger factorial = new Factorial().getFactorial(n); + + // then + BigInteger expectedFactorial = new BigInteger("10329978488239059262599702099394727095397746340117372869212250571234293987594703124871765375385424468563282236864226607350415360000000000000000000000"); + assertThat(factorial, is(equalTo(expectedFactorial))); + } + + @Test + public void givenMemoizedSupplier_whenGet_thenSubsequentGetsAreFast() { + Supplier memoizedSupplier; + memoizedSupplier = Suppliers.memoize(CostlySupplier::generateBigNumber); + + Instant start = Instant.now(); + BigInteger bigNumber = memoizedSupplier.get(); + Long durationInMs = Duration.between(start, Instant.now()).toMillis(); + assertThat(bigNumber, is(equalTo(new BigInteger("12345")))); + assertThat(durationInMs.doubleValue(), is(closeTo(2000D, 100D))); + + start = Instant.now(); + bigNumber = memoizedSupplier.get().add(BigInteger.ONE); + durationInMs = Duration.between(start, Instant.now()).toMillis(); + assertThat(bigNumber, is(equalTo(new BigInteger("12346")))); + assertThat(durationInMs.doubleValue(), is(closeTo(0D, 100D))); + + start = Instant.now(); + bigNumber = memoizedSupplier.get().add(BigInteger.TEN); + durationInMs = Duration.between(start, Instant.now()).toMillis(); + assertThat(bigNumber, is(equalTo(new BigInteger("12355")))); + assertThat(durationInMs.doubleValue(), is(closeTo(0D, 100D))); + } + + @Test + public void givenMemoizedSupplierWithExpiration_whenGet_thenSubsequentGetsBeforeExpiredAreFast() throws InterruptedException { + Supplier memoizedSupplier; + memoizedSupplier = Suppliers.memoizeWithExpiration(CostlySupplier::generateBigNumber, 3, TimeUnit.SECONDS); + + Instant start = Instant.now(); + BigInteger bigNumber = memoizedSupplier.get(); + Long durationInMs = Duration.between(start, Instant.now()).toMillis(); + assertThat(bigNumber, is(equalTo(new BigInteger("12345")))); + assertThat(durationInMs.doubleValue(), is(closeTo(2000D, 100D))); + + start = Instant.now(); + bigNumber = memoizedSupplier.get().add(BigInteger.ONE); + durationInMs = Duration.between(start, Instant.now()).toMillis(); + assertThat(bigNumber, is(equalTo(new BigInteger("12346")))); + assertThat(durationInMs.doubleValue(), is(closeTo(0D, 100D))); + + TimeUnit.SECONDS.sleep(1); + + start = Instant.now(); + bigNumber = memoizedSupplier.get().add(BigInteger.TEN); + durationInMs = Duration.between(start, Instant.now()).toMillis(); + assertThat(bigNumber, is(equalTo(new BigInteger("12355")))); + assertThat(durationInMs.doubleValue(), is(closeTo(2000D, 100D))); + } + +} From be90e9870c12864b651bc2093a8cfea01563805f Mon Sep 17 00:00:00 2001 From: Nam Thai Nguyen Date: Mon, 29 Jan 2018 17:02:48 +0700 Subject: [PATCH 06/28] Initial commit for BAEL-1500 --- .../main/java/com/baeldung/javac/Data.java | 28 +++++++++++++++++++ core-java/src/main/java/javac-args/arguments | 2 ++ core-java/src/main/java/javac-args/options | 2 ++ core-java/src/main/java/javac-args/types | 1 + core-java/src/main/java/javac-args/xlint-ops | 3 ++ 5 files changed, 36 insertions(+) create mode 100644 core-java/src/main/java/com/baeldung/javac/Data.java create mode 100644 core-java/src/main/java/javac-args/arguments create mode 100644 core-java/src/main/java/javac-args/options create mode 100644 core-java/src/main/java/javac-args/types create mode 100644 core-java/src/main/java/javac-args/xlint-ops diff --git a/core-java/src/main/java/com/baeldung/javac/Data.java b/core-java/src/main/java/com/baeldung/javac/Data.java new file mode 100644 index 0000000000..f6912fbd14 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/javac/Data.java @@ -0,0 +1,28 @@ +package com.baeldung.javac; + +import java.io.Serializable; +import java.util.ArrayList; +import java.util.List; + +public class Data implements Serializable { + static List textList = new ArrayList(); + + private static void addText() { + textList.add("baeldung"); + textList.add("."); + textList.add("com"); + } + + public List getTextList() { + this.addText(); + List result = new ArrayList(); + String firstElement = (String) textList.get(0); + switch (firstElement) { + case "baeldung": + result.add("baeldung"); + case "com": + result.add("com"); + } + return result; + } +} diff --git a/core-java/src/main/java/javac-args/arguments b/core-java/src/main/java/javac-args/arguments new file mode 100644 index 0000000000..51639800a7 --- /dev/null +++ b/core-java/src/main/java/javac-args/arguments @@ -0,0 +1,2 @@ +-d javac-target -verbose +com/baeldung/javac/Data.java \ No newline at end of file diff --git a/core-java/src/main/java/javac-args/options b/core-java/src/main/java/javac-args/options new file mode 100644 index 0000000000..f02f2344ff --- /dev/null +++ b/core-java/src/main/java/javac-args/options @@ -0,0 +1,2 @@ +-d javac-target +-verbose \ No newline at end of file diff --git a/core-java/src/main/java/javac-args/types b/core-java/src/main/java/javac-args/types new file mode 100644 index 0000000000..ef2d861f84 --- /dev/null +++ b/core-java/src/main/java/javac-args/types @@ -0,0 +1 @@ +com/baeldung/javac/Data.java \ No newline at end of file diff --git a/core-java/src/main/java/javac-args/xlint-ops b/core-java/src/main/java/javac-args/xlint-ops new file mode 100644 index 0000000000..cdccbc0cce --- /dev/null +++ b/core-java/src/main/java/javac-args/xlint-ops @@ -0,0 +1,3 @@ +-d javac-target +-Xlint:rawtypes,unchecked,static,cast,serial,fallthrough +com/baeldung/javac/Data.java \ No newline at end of file From bdae4fe99bd201f37a187e08f93fa8ca063ddd3a Mon Sep 17 00:00:00 2001 From: abialas Date: Tue, 30 Jan 2018 03:32:09 +0100 Subject: [PATCH 07/28] BAEL-21 new Java9 HTTP API overview (#3536) * BAEL-1412 add java 8 spring data features * BAEL-21 new HTTP API overview --- .../java9/httpclient/HttpClientTest.java | 215 ++++++++++++++++++ .../java9/httpclient/HttpRequestTest.java | 171 ++++++++++++++ .../java9/httpclient/HttpResponseTest.java | 55 +++++ 3 files changed, 441 insertions(+) create mode 100644 core-java-9/src/test/java/com/baeldung/java9/httpclient/HttpClientTest.java create mode 100644 core-java-9/src/test/java/com/baeldung/java9/httpclient/HttpRequestTest.java create mode 100644 core-java-9/src/test/java/com/baeldung/java9/httpclient/HttpResponseTest.java diff --git a/core-java-9/src/test/java/com/baeldung/java9/httpclient/HttpClientTest.java b/core-java-9/src/test/java/com/baeldung/java9/httpclient/HttpClientTest.java new file mode 100644 index 0000000000..a4c6ac0d7d --- /dev/null +++ b/core-java-9/src/test/java/com/baeldung/java9/httpclient/HttpClientTest.java @@ -0,0 +1,215 @@ +package com.baeldung.java9.httpclient; + +import jdk.incubator.http.HttpClient; +import jdk.incubator.http.HttpRequest; +import jdk.incubator.http.HttpResponse; +import org.junit.Test; + +import java.io.IOException; +import java.net.*; +import java.util.Arrays; +import java.util.List; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.stream.Collectors; + +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.collection.IsEmptyCollection.empty; +import static org.hamcrest.core.IsNot.not; +import static org.junit.Assert.assertThat; + +/** + * Created by adam. + */ +public class HttpClientTest { + + @Test + public void shouldReturnSampleDataContentWhenConnectViaSystemProxy() throws IOException, InterruptedException, URISyntaxException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/post")) + .headers("Content-Type", "text/plain;charset=UTF-8") + .POST(HttpRequest.BodyProcessor.fromString("Sample body")) + .build(); + + HttpResponse response = HttpClient.newBuilder() + .proxy(ProxySelector.getDefault()) + .build() + .send(request, HttpResponse.BodyHandler.asString()); + + assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + assertThat(response.body(), containsString("Sample body")); + } + + @Test + public void shouldNotFollowRedirectWhenSetToDefaultNever() throws IOException, InterruptedException, URISyntaxException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("http://stackoverflow.com")) + .version(HttpClient.Version.HTTP_1_1) + .GET() + .build(); + HttpResponse response = HttpClient.newBuilder() + .build() + .send(request, HttpResponse.BodyHandler.asString()); + + assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_MOVED_PERM)); + assertThat(response.body(), containsString("https://stackoverflow.com/")); + } + + @Test + public void shouldFollowRedirectWhenSetToAlways() throws IOException, InterruptedException, URISyntaxException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("http://stackoverflow.com")) + .version(HttpClient.Version.HTTP_1_1) + .GET() + .build(); + HttpResponse response = HttpClient.newBuilder() + .followRedirects(HttpClient.Redirect.ALWAYS) + .build() + .send(request, HttpResponse.BodyHandler.asString()); + + assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + assertThat(response.finalRequest() + .uri() + .toString(), equalTo("https://stackoverflow.com/")); + } + + @Test + public void shouldReturnOKStatusForAuthenticatedAccess() throws URISyntaxException, IOException, InterruptedException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/basic-auth")) + .GET() + .build(); + HttpResponse response = HttpClient.newBuilder() + .authenticator(new Authenticator() { + @Override + protected PasswordAuthentication getPasswordAuthentication() { + return new PasswordAuthentication("postman", "password".toCharArray()); + } + }) + .build() + .send(request, HttpResponse.BodyHandler.asString()); + + assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + } + + @Test + public void shouldSendRequestAsync() throws URISyntaxException, InterruptedException, ExecutionException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/post")) + .headers("Content-Type", "text/plain;charset=UTF-8") + .POST(HttpRequest.BodyProcessor.fromString("Sample body")) + .build(); + CompletableFuture> response = HttpClient.newBuilder() + .build() + .sendAsync(request, HttpResponse.BodyHandler.asString()); + + assertThat(response.get() + .statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + } + + @Test + public void shouldUseJustTwoThreadWhenProcessingSendAsyncRequest() throws URISyntaxException, InterruptedException, ExecutionException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/get")) + .GET() + .build(); + + CompletableFuture> response1 = HttpClient.newBuilder() + .executor(Executors.newFixedThreadPool(2)) + .build() + .sendAsync(request, HttpResponse.BodyHandler.asString()); + + CompletableFuture> response2 = HttpClient.newBuilder() + .executor(Executors.newFixedThreadPool(2)) + .build() + .sendAsync(request, HttpResponse.BodyHandler.asString()); + + CompletableFuture> response3 = HttpClient.newBuilder() + .executor(Executors.newFixedThreadPool(2)) + .build() + .sendAsync(request, HttpResponse.BodyHandler.asString()); + + CompletableFuture.allOf(response1, response2, response3) + .join(); + + assertThat(response1.get() + .statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + assertThat(response2.get() + .statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + assertThat(response3.get() + .statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + } + + @Test + public void shouldNotStoreCookieWhenPolicyAcceptNone() throws URISyntaxException, IOException, InterruptedException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/get")) + .GET() + .build(); + + HttpClient httpClient = HttpClient.newBuilder() + .cookieManager(new CookieManager(null, CookiePolicy.ACCEPT_NONE)) + .build(); + + httpClient.send(request, HttpResponse.BodyHandler.asString()); + + assertThat(httpClient.cookieManager() + .get() + .getCookieStore() + .getCookies(), empty()); + } + + @Test + public void shouldStoreCookieWhenPolicyAcceptAll() throws URISyntaxException, IOException, InterruptedException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/get")) + .GET() + .build(); + + HttpClient httpClient = HttpClient.newBuilder() + .cookieManager(new CookieManager(null, CookiePolicy.ACCEPT_ALL)) + .build(); + + httpClient.send(request, HttpResponse.BodyHandler.asString()); + + assertThat(httpClient.cookieManager() + .get() + .getCookieStore() + .getCookies(), not(empty())); + } + + @Test + public void shouldProcessMultipleRequestViaStream() throws URISyntaxException, ExecutionException, InterruptedException { + List targets = Arrays.asList(new URI("https://postman-echo.com/get?foo1=bar1"), new URI("https://postman-echo.com/get?foo2=bar2")); + + HttpClient client = HttpClient.newHttpClient(); + + List> futures = targets.stream() + .map(target -> client.sendAsync(HttpRequest.newBuilder(target) + .GET() + .build(), HttpResponse.BodyHandler.asString()) + .thenApply(response -> response.body())) + .collect(Collectors.toList()); + + CompletableFuture.allOf(futures.toArray(new CompletableFuture[0])) + .join(); + + if (futures.get(0) + .get() + .contains("foo1")) { + assertThat(futures.get(0) + .get(), containsString("bar1")); + assertThat(futures.get(1) + .get(), containsString("bar2")); + } else { + assertThat(futures.get(1) + .get(), containsString("bar2")); + assertThat(futures.get(1) + .get(), containsString("bar1")); + } + + } + +} diff --git a/core-java-9/src/test/java/com/baeldung/java9/httpclient/HttpRequestTest.java b/core-java-9/src/test/java/com/baeldung/java9/httpclient/HttpRequestTest.java new file mode 100644 index 0000000000..7c0e9a90e0 --- /dev/null +++ b/core-java-9/src/test/java/com/baeldung/java9/httpclient/HttpRequestTest.java @@ -0,0 +1,171 @@ +package com.baeldung.java9.httpclient; + +import jdk.incubator.http.HttpClient; +import jdk.incubator.http.HttpRequest; +import jdk.incubator.http.HttpResponse; +import org.junit.Test; + +import java.io.ByteArrayInputStream; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.URISyntaxException; +import java.nio.file.Paths; +import java.security.NoSuchAlgorithmException; +import java.time.Duration; + +import static java.time.temporal.ChronoUnit.SECONDS; +import static org.hamcrest.CoreMatchers.containsString; +import static org.hamcrest.CoreMatchers.equalTo; +import static org.junit.Assert.assertThat; + +/** + * Created by adam. + */ +public class HttpRequestTest { + + @Test + public void shouldReturnStatusOKWhenSendGetRequest() throws IOException, InterruptedException, URISyntaxException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/get")) + .GET() + .build(); + + HttpResponse response = HttpClient.newHttpClient() + .send(request, HttpResponse.BodyHandler.asString()); + + assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + } + + @Test + public void shouldUseHttp2WhenWebsiteUsesHttp2() throws IOException, InterruptedException, URISyntaxException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://stackoverflow.com")) + .version(HttpClient.Version.HTTP_2) + .GET() + .build(); + HttpResponse response = HttpClient.newHttpClient() + .send(request, HttpResponse.BodyHandler.asString()); + + assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + assertThat(response.version(), equalTo(HttpClient.Version.HTTP_2)); + } + + @Test + public void shouldFallbackToHttp1_1WhenWebsiteDoesNotUseHttp2() throws IOException, InterruptedException, URISyntaxException, NoSuchAlgorithmException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/get")) + .version(HttpClient.Version.HTTP_2) + .GET() + .build(); + + HttpResponse response = HttpClient.newHttpClient() + .send(request, HttpResponse.BodyHandler.asString()); + + assertThat(response.version(), equalTo(HttpClient.Version.HTTP_1_1)); + } + + @Test + public void shouldReturnStatusOKWhenSendGetRequestWithDummyHeaders() throws IOException, InterruptedException, URISyntaxException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/get")) + .headers("key1", "value1", "key2", "value2") + .GET() + .build(); + + HttpResponse response = HttpClient.newHttpClient() + .send(request, HttpResponse.BodyHandler.asString()); + + assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + } + + @Test + public void shouldReturnStatusOKWhenSendGetRequestTimeoutSet() throws IOException, InterruptedException, URISyntaxException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/get")) + .timeout(Duration.of(10, SECONDS)) + .GET() + .build(); + + HttpResponse response = HttpClient.newHttpClient() + .send(request, HttpResponse.BodyHandler.asString()); + + assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + } + + @Test + public void shouldReturnNoContentWhenPostWithNoBody() throws IOException, InterruptedException, URISyntaxException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/post")) + .POST(HttpRequest.noBody()) + .build(); + + HttpResponse response = HttpClient.newHttpClient() + .send(request, HttpResponse.BodyHandler.asString()); + + assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + } + + @Test + public void shouldReturnSampleDataContentWhenPostWithBodyText() throws IOException, InterruptedException, URISyntaxException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/post")) + .headers("Content-Type", "text/plain;charset=UTF-8") + .POST(HttpRequest.BodyProcessor.fromString("Sample request body")) + .build(); + + HttpResponse response = HttpClient.newHttpClient() + .send(request, HttpResponse.BodyHandler.asString()); + + assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + assertThat(response.body(), containsString("Sample request body")); + } + + @Test + public void shouldReturnSampleDataContentWhenPostWithInputStream() throws IOException, InterruptedException, URISyntaxException { + byte[] sampleData = "Sample request body".getBytes(); + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/post")) + .headers("Content-Type", "text/plain;charset=UTF-8") + .POST(HttpRequest.BodyProcessor.fromInputStream(() -> new ByteArrayInputStream(sampleData))) + .build(); + + HttpResponse response = HttpClient.newHttpClient() + .send(request, HttpResponse.BodyHandler.asString()); + + assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + assertThat(response.body(), containsString("Sample request body")); + } + + @Test + public void shouldReturnSampleDataContentWhenPostWithByteArrayProcessorStream() throws IOException, InterruptedException, URISyntaxException { + byte[] sampleData = "Sample request body".getBytes(); + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/post")) + .headers("Content-Type", "text/plain;charset=UTF-8") + .POST(HttpRequest.BodyProcessor.fromByteArray(sampleData)) + .build(); + + HttpResponse response = HttpClient.newHttpClient() + .send(request, HttpResponse.BodyHandler.asString()); + + assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + assertThat(response.body(), containsString("Sample request body")); + } + + @Test + public void shouldReturnSampleDataContentWhenPostWithFileProcessorStream() throws IOException, InterruptedException, URISyntaxException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/post")) + .headers("Content-Type", "text/plain;charset=UTF-8") + .POST(HttpRequest.BodyProcessor.fromFile(Paths.get("src/test/resources/sample.txt"))) + .build(); + + HttpResponse response = HttpClient.newHttpClient() + .send(request, HttpResponse.BodyHandler.asString()); + + assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + assertThat(response.body(), containsString("Sample file content")); + } + +} diff --git a/core-java-9/src/test/java/com/baeldung/java9/httpclient/HttpResponseTest.java b/core-java-9/src/test/java/com/baeldung/java9/httpclient/HttpResponseTest.java new file mode 100644 index 0000000000..80295ff34c --- /dev/null +++ b/core-java-9/src/test/java/com/baeldung/java9/httpclient/HttpResponseTest.java @@ -0,0 +1,55 @@ +package com.baeldung.java9.httpclient; + +import jdk.incubator.http.HttpClient; +import jdk.incubator.http.HttpRequest; +import jdk.incubator.http.HttpResponse; +import org.junit.Test; + +import java.io.IOException; +import java.net.HttpURLConnection; +import java.net.URI; +import java.net.URISyntaxException; + +import static org.hamcrest.CoreMatchers.equalTo; +import static org.hamcrest.Matchers.isEmptyString; +import static org.hamcrest.core.IsNot.not; +import static org.junit.Assert.assertThat; + +/** + * Created by adam. + */ +public class HttpResponseTest { + + @Test + public void shouldReturnStatusOKWhenSendGetRequest() throws IOException, InterruptedException, URISyntaxException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("https://postman-echo.com/get")) + .GET() + .build(); + + HttpResponse response = HttpClient.newHttpClient() + .send(request, HttpResponse.BodyHandler.asString()); + + assertThat(response.statusCode(), equalTo(HttpURLConnection.HTTP_OK)); + assertThat(response.body(), not(isEmptyString())); + } + + @Test + public void shouldResponseURIDifferentThanRequestUIRWhenRedirect() throws IOException, InterruptedException, URISyntaxException { + HttpRequest request = HttpRequest.newBuilder() + .uri(new URI("http://stackoverflow.com")) + .version(HttpClient.Version.HTTP_1_1) + .GET() + .build(); + HttpResponse response = HttpClient.newBuilder() + .followRedirects(HttpClient.Redirect.ALWAYS) + .build() + .send(request, HttpResponse.BodyHandler.asString()); + + assertThat(request.uri() + .toString(), equalTo("http://stackoverflow.com")); + assertThat(response.uri() + .toString(), equalTo("https://stackoverflow.com/")); + } + +} From 32e309ae4d62f3b38334ad60977660cb55c1deff Mon Sep 17 00:00:00 2001 From: Ganesh Date: Tue, 30 Jan 2018 20:25:08 +0530 Subject: [PATCH 08/28] BAEL-1456 - How to implement task prioritization in Java (#3366) * priority based job execution in java * minor fixes * updated to use java 8 features --- .../concurrent/prioritytaskexecution/Job.java | 24 ++++++++ .../prioritytaskexecution/JobPriority.java | 7 +++ .../PriorityJobScheduler.java | 56 +++++++++++++++++++ .../PriorityJobSchedulerUnitTest.java | 38 +++++++++++++ 4 files changed, 125 insertions(+) create mode 100644 core-java-concurrency/src/main/java/com/baeldung/concurrent/prioritytaskexecution/Job.java create mode 100644 core-java-concurrency/src/main/java/com/baeldung/concurrent/prioritytaskexecution/JobPriority.java create mode 100644 core-java-concurrency/src/main/java/com/baeldung/concurrent/prioritytaskexecution/PriorityJobScheduler.java create mode 100644 core-java-concurrency/src/test/java/com/baeldung/concurrent/prioritytaskexecution/PriorityJobSchedulerUnitTest.java diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/prioritytaskexecution/Job.java b/core-java-concurrency/src/main/java/com/baeldung/concurrent/prioritytaskexecution/Job.java new file mode 100644 index 0000000000..a70041ed7d --- /dev/null +++ b/core-java-concurrency/src/main/java/com/baeldung/concurrent/prioritytaskexecution/Job.java @@ -0,0 +1,24 @@ +package com.baeldung.concurrent.prioritytaskexecution; + +public class Job implements Runnable { + private String jobName; + private JobPriority jobPriority; + + public Job(String jobName, JobPriority jobPriority) { + this.jobName = jobName; + this.jobPriority = jobPriority != null ? jobPriority : JobPriority.MEDIUM; + } + + public JobPriority getJobPriority() { + return jobPriority; + } + + @Override + public void run() { + try { + System.out.println("Job:" + jobName + " Priority:" + jobPriority); + Thread.sleep(1000); + } catch (InterruptedException ignored) { + } + } +} \ No newline at end of file diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/prioritytaskexecution/JobPriority.java b/core-java-concurrency/src/main/java/com/baeldung/concurrent/prioritytaskexecution/JobPriority.java new file mode 100644 index 0000000000..d8092a9ce7 --- /dev/null +++ b/core-java-concurrency/src/main/java/com/baeldung/concurrent/prioritytaskexecution/JobPriority.java @@ -0,0 +1,7 @@ +package com.baeldung.concurrent.prioritytaskexecution; + +public enum JobPriority { + HIGH, + MEDIUM, + LOW +} diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/prioritytaskexecution/PriorityJobScheduler.java b/core-java-concurrency/src/main/java/com/baeldung/concurrent/prioritytaskexecution/PriorityJobScheduler.java new file mode 100644 index 0000000000..70fd1710c0 --- /dev/null +++ b/core-java-concurrency/src/main/java/com/baeldung/concurrent/prioritytaskexecution/PriorityJobScheduler.java @@ -0,0 +1,56 @@ +package com.baeldung.concurrent.prioritytaskexecution; + +import java.util.Comparator; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.PriorityBlockingQueue; +import java.util.concurrent.TimeUnit; + +public class PriorityJobScheduler { + + private ExecutorService priorityJobPoolExecutor; + private ExecutorService priorityJobScheduler; + private PriorityBlockingQueue priorityQueue; + + public PriorityJobScheduler(Integer poolSize, Integer queueSize) { + priorityJobPoolExecutor = Executors.newFixedThreadPool(poolSize); + Comparator jobComparator = Comparator.comparing(Job::getJobPriority); + priorityQueue = new PriorityBlockingQueue(queueSize, + (Comparator) jobComparator); + + priorityJobScheduler = Executors.newSingleThreadExecutor(); + priorityJobScheduler.execute(()->{ + while (true) { + try { + priorityJobPoolExecutor.execute(priorityQueue.take()); + } catch (InterruptedException e) { + break; + } + } + }); + } + + public void scheduleJob(Job job) { + priorityQueue.add(job); + } + + public int getQueuedTaskCount() { + return priorityQueue.size(); + } + + protected void close(ExecutorService scheduler) { + scheduler.shutdown(); + try { + if (!scheduler.awaitTermination(5, TimeUnit.SECONDS)) { + scheduler.shutdownNow(); + } + } catch (InterruptedException e) { + scheduler.shutdownNow(); + } + } + + public void closeScheduler() { + close(priorityJobPoolExecutor); + close(priorityJobScheduler); + } +} diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/prioritytaskexecution/PriorityJobSchedulerUnitTest.java b/core-java-concurrency/src/test/java/com/baeldung/concurrent/prioritytaskexecution/PriorityJobSchedulerUnitTest.java new file mode 100644 index 0000000000..902bada3a2 --- /dev/null +++ b/core-java-concurrency/src/test/java/com/baeldung/concurrent/prioritytaskexecution/PriorityJobSchedulerUnitTest.java @@ -0,0 +1,38 @@ +package com.baeldung.concurrent.prioritytaskexecution; + +import org.junit.Test; + +public class PriorityJobSchedulerUnitTest { + private static int POOL_SIZE = 1; + private static int QUEUE_SIZE = 10; + + @Test + public void whenMultiplePriorityJobsQueued_thenHighestPriorityJobIsPicked() { + Job job1 = new Job("Job1", JobPriority.LOW); + Job job2 = new Job("Job2", JobPriority.MEDIUM); + Job job3 = new Job("Job3", JobPriority.HIGH); + Job job4 = new Job("Job4", JobPriority.MEDIUM); + Job job5 = new Job("Job5", JobPriority.LOW); + Job job6 = new Job("Job6", JobPriority.HIGH); + + PriorityJobScheduler pjs = new PriorityJobScheduler(POOL_SIZE, QUEUE_SIZE); + + pjs.scheduleJob(job1); + pjs.scheduleJob(job2); + pjs.scheduleJob(job3); + pjs.scheduleJob(job4); + pjs.scheduleJob(job5); + pjs.scheduleJob(job6); + + // ensure no tasks is pending before closing the scheduler + while (pjs.getQueuedTaskCount() != 0); + + // delay to avoid job sleep (added for demo) being interrupted + try { + Thread.sleep(2000); + } catch (InterruptedException ignored) { + } + + pjs.closeScheduler(); + } +} From f6cfff3f9d2be2018af280b2647bb3a01081d715 Mon Sep 17 00:00:00 2001 From: iaforek Date: Tue, 30 Jan 2018 18:13:53 +0000 Subject: [PATCH 09/28] BAEL-1298 - How to create a Sudoku solver (#3197) * Code for Dependency Injection Article. * Added Java based configuration. Downloaded formatter.xml and reformatted all changed files. Manually changed tab into 4 spaces in XML configuration files. * BAEL-434 - Spring Roo project files generated by Spring Roo. No formatting applied. Added POM, java and resources folders. * Moved project from roo to spring-roo folder. * BAEL-838 Initial code showing how to remove last char - helper class and tests. * BAEL-838 Corrected Helper class and associated empty string test case. Added StringUtils.substing tests. * BAEL-838 Refromatted code using formatter.xml. Added Assert.assertEquals import. Renamed test to follow convention. Reordered tests. * BAEL-838 - Added regex method and updated tests. * BAEL-838 Added new line examples. * BAEL-838 Renamed RemoveLastChar class to StringHelper and added Java8 examples. Refactord code. * BAEL-838 Changed method names * BAEL-838 Tiny change to keep code consistant. Return null or empty. * BAEL-838 Removed unresolved conflict. * BAEL-821 New class that shows different rounding techniques. Updated POM. * BAEL-821 - Added unit test for different round methods. * BAEL-821 Changed test method name to follow the convention * BAEL-821 Added more test and updated round methods. * BAEL-837 - initial commit. A few examples of adding doubles. * BAEL-837 - Couple of smaller changes * BAEL-837 - Added jUnit test. * BAEL-579 Updated Spring Cloud Version I was getting error: java.lang.NoSuchMethodError: org.springframework.cloud.config.environment.Environment After version update, all is okay. * BAEL-579 Added actuator to Cloud Config Client. * BAEL-579 Enabled cloud bus and updated dependencies. * BAEL-579 Config Client using Spring Cloud Bus. * BAEL-579 Recreated Basic Config Server. * BAEL-579 Recreated Config Client. * BAEL-579 Removed test Git URL. * BAEL-579 Added Actuator to Config Client * BAEL-579 Added Spring Cloud Bus to Client. * BAEL-579 Server changes for Spring Cloud Bus Added dependencies and removed git.clone-on-start as this was causing server to throw errors after git properties change. * BAEL-579 Removed Git URL. * Revert "BAEL-579 Updated Spring Cloud Version" This reverts commit f775bf91e53a1ecfb9b70596688d7c8202bf495f. * Revert "BAEL-579 Config Client using Spring Cloud Bus." This reverts commit 1d96bc5761994a33af9a7a9aa5ab68604a5b44dc. * Revert "BAEL-579 Enabled cloud bus and updated dependencies." This reverts commit 7845da922d89d53506dd0fff387ea13694c50bc1. * Revert "BAEL-579 Added actuator to Cloud Config Client." This reverts commit 076657a26a57e0aa676989a4d97966a3b9d53e1c. * BAEL-579 Added missing dependency versions. * BAEL-579 Added missing dependency versions. * Updated gitignore * BAEL-1065 Simple performance check StringBuffer vs StringBuilder. * BAEL-1065 Added JMH benchmarks * BAEL-1298 Sudoku - Backtracking Algorithm * BAEL-1298 Sudoku - Backtracking Algorithm * BAEL-1298 Dancing Links Algorithm. Smaller changes to Backtracking * BAEL-1298 Resolve conflict - use most up-to-date POM * Updated code - mostly with CONSTANTS. Extracted methods. * Removed pointless Java8 code. Renamed constant --- .../sudoku/BacktrackingAlgorithm.java | 103 ++++++++++++++ .../algorithms/sudoku/ColumnNode.java | 33 +++++ .../algorithms/sudoku/DancingLinks.java | 134 ++++++++++++++++++ .../sudoku/DancingLinksAlgorithm.java | 110 ++++++++++++++ .../algorithms/sudoku/DancingNode.java | 50 +++++++ 5 files changed, 430 insertions(+) create mode 100644 algorithms/src/main/java/com/baeldung/algorithms/sudoku/BacktrackingAlgorithm.java create mode 100644 algorithms/src/main/java/com/baeldung/algorithms/sudoku/ColumnNode.java create mode 100644 algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingLinks.java create mode 100644 algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingLinksAlgorithm.java create mode 100644 algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingNode.java diff --git a/algorithms/src/main/java/com/baeldung/algorithms/sudoku/BacktrackingAlgorithm.java b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/BacktrackingAlgorithm.java new file mode 100644 index 0000000000..127e78900c --- /dev/null +++ b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/BacktrackingAlgorithm.java @@ -0,0 +1,103 @@ +package com.baeldung.algorithms.sudoku; + +import java.util.stream.IntStream; + +public class BacktrackingAlgorithm { + + private static int BOARD_SIZE = 9; + private static int SUBSECTION_SIZE = 3; + private static int BOARD_START_INDEX = 0; + + private static int NO_VALUE = 0; + private static int MIN_VALUE = 1; + private static int MAX_VALUE = 9; + + public static int[][] board = { + { 8, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 3, 6, 0, 0, 0, 0, 0 }, + { 0, 7, 0, 0, 9, 0, 2, 0, 0 }, + { 0, 5, 0, 0, 0, 7, 0, 0, 0 }, + { 0, 0, 0, 0, 4, 5, 7, 0, 0 }, + { 0, 0, 0, 1, 0, 0, 0, 3, 0 }, + { 0, 0, 1, 0, 0, 0, 0, 6, 8 }, + { 0, 0, 8, 5, 0, 0, 0, 1, 0 }, + { 0, 9, 0, 0, 0, 0, 4, 0, 0 } + }; + + public static void main(String[] args) { + BacktrackingAlgorithm solver = new BacktrackingAlgorithm(); + solver.solve(board); + solver.printBoard(); + } + + public void printBoard() { + for (int row = BOARD_START_INDEX; row < BOARD_SIZE; row++) { + for (int column = BOARD_START_INDEX; column < BOARD_SIZE; column++) { + System.out.print(board[row][column] + " "); + } + System.out.println(); + } + } + + public boolean solve(int[][] board) { + for (int r = BOARD_START_INDEX; r < BOARD_SIZE; r++) { + for (int c = BOARD_START_INDEX; c < BOARD_SIZE; c++) { + if (board[r][c] == NO_VALUE) { + for (int k = MIN_VALUE; k <= MAX_VALUE; k++) { + board[r][c] = k; + if (isValid(board, r, c) && solve(board)) { + return true; + } else { + board[r][c] = NO_VALUE; + } + } + return false; + } + } + } + return true; + } + + public boolean isValid(int[][] board, int r, int c) { + return (rowConstraint(board, r) && + columnConstraint(board, c) && + subsectionConstraint(board, r, c)); + } + + private boolean subsectionConstraint(int[][] board, int r, int c) { + boolean[] constraint = new boolean[BOARD_SIZE]; + for (int i = (r / SUBSECTION_SIZE) * SUBSECTION_SIZE; i < (r / SUBSECTION_SIZE) * SUBSECTION_SIZE + SUBSECTION_SIZE; i++) { + for (int j = (c / SUBSECTION_SIZE) * SUBSECTION_SIZE; j < (c / SUBSECTION_SIZE) * SUBSECTION_SIZE + SUBSECTION_SIZE; j++) { + if (!checkConstraint(board, i, constraint, j)) return false; + } + } + return true; + } + + private boolean columnConstraint(int[][] board, int c) { + boolean[] constraint = new boolean[BOARD_SIZE]; + for (int i = BOARD_START_INDEX; i < BOARD_SIZE; i++) { + if (!checkConstraint(board, i, constraint, c)) return false; + } + return true; + } + + private boolean rowConstraint(int[][] board, int r) { + boolean[] constraint = new boolean[BOARD_SIZE]; + for (int i = BOARD_START_INDEX; i < BOARD_SIZE; i++) { + if (!checkConstraint(board, r, constraint, i)) return false; + } + return true; + } + + private boolean checkConstraint(int[][] board, int r, boolean[] constraint, int c) { + if (board[r][c] >= MIN_VALUE && board[r][c] <= MAX_VALUE) { + if (constraint[board[r][c] - 1] == false) { + constraint[board[r][c] - 1] = true; + } else { + return false; + } + } + return true; + } +} diff --git a/algorithms/src/main/java/com/baeldung/algorithms/sudoku/ColumnNode.java b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/ColumnNode.java new file mode 100644 index 0000000000..48538344b6 --- /dev/null +++ b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/ColumnNode.java @@ -0,0 +1,33 @@ +package com.baeldung.algorithms.sudoku; + +class ColumnNode extends DancingNode { + int size; + String name; + + public ColumnNode(String n) { + super(); + size = 0; + name = n; + C = this; + } + + void cover() { + unlinkLR(); + for (DancingNode i = this.D; i != this; i = i.D) { + for (DancingNode j = i.R; j != i; j = j.R) { + j.unlinkUD(); + j.C.size--; + } + } + } + + void uncover() { + for (DancingNode i = this.U; i != this; i = i.U) { + for (DancingNode j = i.L; j != i; j = j.L) { + j.C.size++; + j.relinkUD(); + } + } + relinkLR(); + } +} \ No newline at end of file diff --git a/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingLinks.java b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingLinks.java new file mode 100644 index 0000000000..a30f8ecab5 --- /dev/null +++ b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingLinks.java @@ -0,0 +1,134 @@ +package com.baeldung.algorithms.sudoku; + +import java.util.ArrayList; +import java.util.LinkedList; +import java.util.List; + +public class DancingLinks { + + private ColumnNode header; + private List answer; + + private void search(int k) { + if (header.R == header) { + handleSolution(answer); + } else { + ColumnNode c = selectColumnNodeHeuristic(); + c.cover(); + + for (DancingNode r = c.D; r != c; r = r.D) { + answer.add(r); + + for (DancingNode j = r.R; j != r; j = j.R) { + j.C.cover(); + } + + search(k + 1); + + r = answer.remove(answer.size() - 1); + c = r.C; + + for (DancingNode j = r.L; j != r; j = j.L) { + j.C.uncover(); + } + } + c.uncover(); + } + } + + private ColumnNode selectColumnNodeHeuristic() { + int min = Integer.MAX_VALUE; + ColumnNode ret = null; + for (ColumnNode c = (ColumnNode) header.R; c != header; c = (ColumnNode) c.R) { + if (c.size < min) { + min = c.size; + ret = c; + } + } + return ret; + } + + private ColumnNode makeDLXBoard(boolean[][] grid) { + final int COLS = grid[0].length; + final int ROWS = grid.length; + + ColumnNode headerNode = new ColumnNode("header"); + ArrayList columnNodes = new ArrayList(); + + for (int i = 0; i < COLS; i++) { + ColumnNode n = new ColumnNode(Integer.toString(i)); + columnNodes.add(n); + headerNode = (ColumnNode) headerNode.hookRight(n); + } + headerNode = headerNode.R.C; + + for (int i = 0; i < ROWS; i++) { + DancingNode prev = null; + for (int j = 0; j < COLS; j++) { + if (grid[i][j] == true) { + ColumnNode col = columnNodes.get(j); + DancingNode newNode = new DancingNode(col); + if (prev == null) + prev = newNode; + col.U.hookDown(newNode); + prev = prev.hookRight(newNode); + col.size++; + } + } + } + + headerNode.size = COLS; + + return headerNode; + } + + public DancingLinks(boolean[][] cover) { + header = makeDLXBoard(cover); + } + + public void runSolver() { + answer = new LinkedList(); + search(0); + } + + public void handleSolution(List answer) { + int[][] result = parseBoard(answer); + printSolution(result); + } + + int size = 9; + + private int[][] parseBoard(List answer) { + int[][] result = new int[size][size]; + for (DancingNode n : answer) { + DancingNode rcNode = n; + int min = Integer.parseInt(rcNode.C.name); + for (DancingNode tmp = n.R; tmp != n; tmp = tmp.R) { + int val = Integer.parseInt(tmp.C.name); + if (val < min) { + min = val; + rcNode = tmp; + } + } + int ans1 = Integer.parseInt(rcNode.C.name); + int ans2 = Integer.parseInt(rcNode.R.C.name); + int r = ans1 / size; + int c = ans1 % size; + int num = (ans2 % size) + 1; + result[r][c] = num; + } + return result; + } + + public static void printSolution(int[][] result) { + int N = result.length; + for (int i = 0; i < N; i++) { + String ret = ""; + for (int j = 0; j < N; j++) { + ret += result[i][j] + " "; + } + System.out.println(ret); + } + System.out.println(); + } +} diff --git a/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingLinksAlgorithm.java b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingLinksAlgorithm.java new file mode 100644 index 0000000000..057a15c594 --- /dev/null +++ b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingLinksAlgorithm.java @@ -0,0 +1,110 @@ +package com.baeldung.algorithms.sudoku; + +import java.util.*; + +public class DancingLinksAlgorithm { + private static int BOARD_SIZE = 9; + private static int SUBSECTION_SIZE = 3; + private static int NO_VALUE = 0; + private static int CONSTRAINTS = 4; + private static int MIN_VALUE = 1; + private static int MAX_VALUE = 9; + private static int COVER_START_INDEX = 1; + + public static int[][] board = { + { 8, 0, 0, 0, 0, 0, 0, 0, 0 }, + { 0, 0, 3, 6, 0, 0, 0, 0, 0 }, + { 0, 7, 0, 0, 9, 0, 2, 0, 0 }, + { 0, 5, 0, 0, 0, 7, 0, 0, 0 }, + { 0, 0, 0, 0, 4, 5, 7, 0, 0 }, + { 0, 0, 0, 1, 0, 0, 0, 3, 0 }, + { 0, 0, 1, 0, 0, 0, 0, 6, 8 }, + { 0, 0, 8, 5, 0, 0, 0, 1, 0 }, + { 0, 9, 0, 0, 0, 0, 4, 0, 0 } + }; + + public static void main(String[] args) { + DancingLinksAlgorithm solver = new DancingLinksAlgorithm(); + solver.solve(board); + } + + public boolean solve(int[][] board) { + boolean[][] cover = initializeExactCoverBoard(board); + DancingLinks dlx = new DancingLinks(cover); + dlx.runSolver(); + + return true; + } + + private int getIndex(int row, int col, int num) { + return (row - 1) * BOARD_SIZE * BOARD_SIZE + (col - 1) * BOARD_SIZE + (num - 1); + } + + private boolean[][] createExactCoverBoard() { + boolean[][] R = new boolean[BOARD_SIZE * BOARD_SIZE * MAX_VALUE][BOARD_SIZE * BOARD_SIZE * CONSTRAINTS]; + + int hBase = 0; + + // Cell constraint. + for (int r = COVER_START_INDEX; r <= BOARD_SIZE; r++) { + for (int c = COVER_START_INDEX; c <= BOARD_SIZE; c++, hBase++) { + for (int n = COVER_START_INDEX; n <= BOARD_SIZE; n++) { + int index = getIndex(r, c, n); + R[index][hBase] = true; + } + } + } + + // Row constrain. + for (int r = COVER_START_INDEX; r <= BOARD_SIZE; r++) { + for (int n = COVER_START_INDEX; n <= BOARD_SIZE; n++, hBase++) { + for (int c1 = COVER_START_INDEX; c1 <= BOARD_SIZE; c1++) { + int index = getIndex(r, c1, n); + R[index][hBase] = true; + } + } + } + + // Column constraint. + for (int c = COVER_START_INDEX; c <= BOARD_SIZE; c++) { + for (int n = COVER_START_INDEX; n <= BOARD_SIZE; n++, hBase++) { + for (int r1 = COVER_START_INDEX; r1 <= BOARD_SIZE; r1++) { + int index = getIndex(r1, c, n); + R[index][hBase] = true; + } + } + } + + // Subsection constraint + for (int br = COVER_START_INDEX; br <= BOARD_SIZE; br += SUBSECTION_SIZE) { + for (int bc = COVER_START_INDEX; bc <= BOARD_SIZE; bc += SUBSECTION_SIZE) { + for (int n = COVER_START_INDEX; n <= BOARD_SIZE; n++, hBase++) { + for (int rDelta = 0; rDelta < SUBSECTION_SIZE; rDelta++) { + for (int cDelta = 0; cDelta < SUBSECTION_SIZE; cDelta++) { + int index = getIndex(br + rDelta, bc + cDelta, n); + R[index][hBase] = true; + } + } + } + } + } + return R; + } + + private boolean[][] initializeExactCoverBoard(int[][] board) { + boolean[][] R = createExactCoverBoard(); + for (int i = COVER_START_INDEX; i <= BOARD_SIZE; i++) { + for (int j = COVER_START_INDEX; j <= BOARD_SIZE; j++) { + int n = board[i - 1][j - 1]; + if (n != NO_VALUE) { + for (int num = MIN_VALUE; num <= MAX_VALUE; num++) { + if (num != n) { + Arrays.fill(R[getIndex(i, j, num)], false); + } + } + } + } + } + return R; + } +} \ No newline at end of file diff --git a/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingNode.java b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingNode.java new file mode 100644 index 0000000000..13dc3f2b57 --- /dev/null +++ b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingNode.java @@ -0,0 +1,50 @@ +package com.baeldung.algorithms.sudoku; + +class DancingNode { + DancingNode L, R, U, D; + ColumnNode C; + + DancingNode hookDown(DancingNode n1) { + assert (this.C == n1.C); + n1.D = this.D; + n1.D.U = n1; + n1.U = this; + this.D = n1; + return n1; + } + + DancingNode hookRight(DancingNode n1) { + n1.R = this.R; + n1.R.L = n1; + n1.L = this; + this.R = n1; + return n1; + } + + void unlinkLR() { + this.L.R = this.R; + this.R.L = this.L; + } + + void relinkLR() { + this.L.R = this.R.L = this; + } + + void unlinkUD() { + this.U.D = this.D; + this.D.U = this.U; + } + + void relinkUD() { + this.U.D = this.D.U = this; + } + + public DancingNode() { + L = R = U = D = this; + } + + public DancingNode(ColumnNode c) { + this(); + C = c; + } +} \ No newline at end of file From a48e0625987442bd490766828d10187afc1ebbce Mon Sep 17 00:00:00 2001 From: mkuligowski Date: Tue, 30 Jan 2018 22:49:54 +0100 Subject: [PATCH 10/28] BAEL-1204 (#3508) * Initialize smooks subproject * Add Smooks dependency * Delete files form badly created submodule * Add domain classes * Create class responsible for converting Orders * Create class responsible for validating messages * Add configuration file * Add integration tests for Smooks converters and validators * ADd en_US locale and fix date format * Fix number format in expected messages * Delete unused mapping * Remove unused conversion to JSON * Add assertion for ruleName in givenIncorrectOrderXML_whenValidate_thenExpectValidationErrors --- libraries/pom.xml | 6 ++ .../smooks/converter/OrderConverter.java | 45 ++++++++++++ .../smooks/converter/OrderValidator.java | 27 +++++++ .../java/com/baeldung/smooks/model/Item.java | 71 +++++++++++++++++++ .../java/com/baeldung/smooks/model/Order.java | 52 ++++++++++++++ .../com/baeldung/smooks/model/Status.java | 5 ++ .../com/baeldung/smooks/model/Supplier.java | 49 +++++++++++++ libraries/src/main/resources/smooks/email.ftl | 8 +++ .../src/main/resources/smooks/item-rules.csv | 1 + libraries/src/main/resources/smooks/order.ftl | 7 ++ .../src/main/resources/smooks/order.json | 21 ++++++ libraries/src/main/resources/smooks/order.xml | 20 ++++++ .../main/resources/smooks/smooks-mapping.xml | 29 ++++++++ .../resources/smooks/smooks-transform-edi.xml | 11 +++ .../smooks/smooks-transform-email.xml | 12 ++++ .../resources/smooks/smooks-validation.xml | 17 +++++ .../main/resources/smooks/supplier.properties | 2 + .../converter/SmooksIntegrationTest.java | 70 ++++++++++++++++++ 18 files changed, 453 insertions(+) create mode 100644 libraries/src/main/java/com/baeldung/smooks/converter/OrderConverter.java create mode 100644 libraries/src/main/java/com/baeldung/smooks/converter/OrderValidator.java create mode 100644 libraries/src/main/java/com/baeldung/smooks/model/Item.java create mode 100644 libraries/src/main/java/com/baeldung/smooks/model/Order.java create mode 100644 libraries/src/main/java/com/baeldung/smooks/model/Status.java create mode 100644 libraries/src/main/java/com/baeldung/smooks/model/Supplier.java create mode 100644 libraries/src/main/resources/smooks/email.ftl create mode 100644 libraries/src/main/resources/smooks/item-rules.csv create mode 100644 libraries/src/main/resources/smooks/order.ftl create mode 100644 libraries/src/main/resources/smooks/order.json create mode 100644 libraries/src/main/resources/smooks/order.xml create mode 100644 libraries/src/main/resources/smooks/smooks-mapping.xml create mode 100644 libraries/src/main/resources/smooks/smooks-transform-edi.xml create mode 100644 libraries/src/main/resources/smooks/smooks-transform-email.xml create mode 100644 libraries/src/main/resources/smooks/smooks-validation.xml create mode 100644 libraries/src/main/resources/smooks/supplier.properties create mode 100644 libraries/src/test/java/com/baeldung/smooks/converter/SmooksIntegrationTest.java diff --git a/libraries/pom.xml b/libraries/pom.xml index 3e802e76c8..a330494bb3 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -710,6 +710,11 @@ test test + + org.milyn + milyn-smooks-all + ${smooks.version} + @@ -789,6 +794,7 @@ 1.23.0 v4-rev493-1.21.0 1.0.0 + 1.7.0 3.0.14 \ No newline at end of file diff --git a/libraries/src/main/java/com/baeldung/smooks/converter/OrderConverter.java b/libraries/src/main/java/com/baeldung/smooks/converter/OrderConverter.java new file mode 100644 index 0000000000..d11f5a29b2 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/smooks/converter/OrderConverter.java @@ -0,0 +1,45 @@ +package com.baeldung.smooks.converter; + +import com.baeldung.smooks.model.Order; +import org.milyn.Smooks; +import org.milyn.payload.JavaResult; +import org.milyn.payload.StringResult; +import org.xml.sax.SAXException; + +import javax.xml.transform.stream.StreamSource; +import java.io.IOException; + +public class OrderConverter { + + public Order convertOrderXMLToOrderObject(String path) throws IOException, SAXException { + Smooks smooks = new Smooks(OrderConverter.class.getResourceAsStream("/smooks/smooks-mapping.xml")); + try { + JavaResult javaResult = new JavaResult(); + smooks.filterSource(new StreamSource(OrderConverter.class.getResourceAsStream(path)), javaResult); + return (Order) javaResult.getBean("order"); + } finally { + smooks.close(); + } + } + + + public String convertOrderXMLtoEDIFACT(String path) throws IOException, SAXException { + return convertDocumentWithTempalte(path, "/smooks/smooks-transform-edi.xml"); + } + + public String convertOrderXMLtoEmailMessage(String path) throws IOException, SAXException { + return convertDocumentWithTempalte(path, "/smooks/smooks-transform-email.xml"); + } + + private String convertDocumentWithTempalte(String path, String config) throws IOException, SAXException { + Smooks smooks = new Smooks(config); + + try { + StringResult stringResult = new StringResult(); + smooks.filterSource(new StreamSource(OrderConverter.class.getResourceAsStream(path)), stringResult); + return stringResult.toString(); + } finally { + smooks.close(); + } + } +} diff --git a/libraries/src/main/java/com/baeldung/smooks/converter/OrderValidator.java b/libraries/src/main/java/com/baeldung/smooks/converter/OrderValidator.java new file mode 100644 index 0000000000..3975921da0 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/smooks/converter/OrderValidator.java @@ -0,0 +1,27 @@ +package com.baeldung.smooks.converter; + +import org.milyn.Smooks; +import org.milyn.payload.JavaResult; +import org.milyn.payload.StringResult; +import org.milyn.validation.ValidationResult; +import org.xml.sax.SAXException; + +import javax.xml.transform.stream.StreamSource; +import java.io.IOException; + +public class OrderValidator { + + public ValidationResult validate(String path) throws IOException, SAXException { + Smooks smooks = new Smooks(OrderValidator.class.getResourceAsStream("/smooks/smooks-validation.xml")); + + try { + StringResult xmlResult = new StringResult(); + JavaResult javaResult = new JavaResult(); + ValidationResult validationResult = new ValidationResult(); + smooks.filterSource(new StreamSource(OrderValidator.class.getResourceAsStream(path)), xmlResult, javaResult, validationResult); + return validationResult; + } finally { + smooks.close(); + } + } +} diff --git a/libraries/src/main/java/com/baeldung/smooks/model/Item.java b/libraries/src/main/java/com/baeldung/smooks/model/Item.java new file mode 100644 index 0000000000..a7f7783b3f --- /dev/null +++ b/libraries/src/main/java/com/baeldung/smooks/model/Item.java @@ -0,0 +1,71 @@ +package com.baeldung.smooks.model; + +public class Item { + + public Item() { + } + + public Item(String code, Double price, Integer quantity) { + this.code = code; + this.price = price; + this.quantity = quantity; + } + + private String code; + private Double price; + private Integer quantity; + + + public String getCode() { + return code; + } + + public void setCode(String code) { + this.code = code; + } + + public Double getPrice() { + return price; + } + + public void setPrice(Double price) { + this.price = price; + } + + public Integer getQuantity() { + return quantity; + } + + public void setQuantity(Integer quantity) { + this.quantity = quantity; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Item item = (Item) o; + + if (code != null ? !code.equals(item.code) : item.code != null) return false; + if (price != null ? !price.equals(item.price) : item.price != null) return false; + return quantity != null ? quantity.equals(item.quantity) : item.quantity == null; + } + + @Override + public int hashCode() { + int result = code != null ? code.hashCode() : 0; + result = 31 * result + (price != null ? price.hashCode() : 0); + result = 31 * result + (quantity != null ? quantity.hashCode() : 0); + return result; + } + + @Override + public String toString() { + return "Item{" + + "code='" + code + '\'' + + ", price=" + price + + ", quantity=" + quantity + + '}'; + } +} diff --git a/libraries/src/main/java/com/baeldung/smooks/model/Order.java b/libraries/src/main/java/com/baeldung/smooks/model/Order.java new file mode 100644 index 0000000000..047e1fe8a3 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/smooks/model/Order.java @@ -0,0 +1,52 @@ +package com.baeldung.smooks.model; + +import java.util.Date; +import java.util.List; + +public class Order { + private Date creationDate; + private Long number; + private Status status; + private Supplier supplier; + private List items; + + public Date getCreationDate() { + return creationDate; + } + + public void setCreationDate(Date creationDate) { + this.creationDate = creationDate; + } + + public Long getNumber() { + return number; + } + + public void setNumber(Long number) { + this.number = number; + } + + public Status getStatus() { + return status; + } + + public void setStatus(Status status) { + this.status = status; + } + + public Supplier getSupplier() { + return supplier; + } + + public void setSupplier(Supplier supplier) { + this.supplier = supplier; + } + + public List getItems() { + return items; + } + + public void setItems(List items) { + this.items = items; + } +} diff --git a/libraries/src/main/java/com/baeldung/smooks/model/Status.java b/libraries/src/main/java/com/baeldung/smooks/model/Status.java new file mode 100644 index 0000000000..53c50bdf46 --- /dev/null +++ b/libraries/src/main/java/com/baeldung/smooks/model/Status.java @@ -0,0 +1,5 @@ +package com.baeldung.smooks.model; + +public enum Status { + NEW, IN_PROGRESS, FINISHED +} diff --git a/libraries/src/main/java/com/baeldung/smooks/model/Supplier.java b/libraries/src/main/java/com/baeldung/smooks/model/Supplier.java new file mode 100644 index 0000000000..31a9e1f43f --- /dev/null +++ b/libraries/src/main/java/com/baeldung/smooks/model/Supplier.java @@ -0,0 +1,49 @@ +package com.baeldung.smooks.model; + +public class Supplier { + + private String name; + private String phoneNumber; + + public Supplier() { + } + + public Supplier(String name, String phoneNumber) { + this.name = name; + this.phoneNumber = phoneNumber; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getPhoneNumber() { + return phoneNumber; + } + + public void setPhoneNumber(String phoneNumber) { + this.phoneNumber = phoneNumber; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + + Supplier supplier = (Supplier) o; + + if (name != null ? !name.equals(supplier.name) : supplier.name != null) return false; + return phoneNumber != null ? phoneNumber.equals(supplier.phoneNumber) : supplier.phoneNumber == null; + } + + @Override + public int hashCode() { + int result = name != null ? name.hashCode() : 0; + result = 31 * result + (phoneNumber != null ? phoneNumber.hashCode() : 0); + return result; + } +} diff --git a/libraries/src/main/resources/smooks/email.ftl b/libraries/src/main/resources/smooks/email.ftl new file mode 100644 index 0000000000..8413046508 --- /dev/null +++ b/libraries/src/main/resources/smooks/email.ftl @@ -0,0 +1,8 @@ +<#setting locale="en_US"> +Hi, +Order number #${order.number} created on ${order.creationDate?string["yyyy-MM-dd"]} is currently in ${order.status} status. +Consider contact supplier "${supplier.name}" with phone number: "${supplier.phoneNumber}". +Order items: +<#list items as item> +${item.quantity} X ${item.code} (total price ${item.price * item.quantity}) + \ No newline at end of file diff --git a/libraries/src/main/resources/smooks/item-rules.csv b/libraries/src/main/resources/smooks/item-rules.csv new file mode 100644 index 0000000000..c93c453f25 --- /dev/null +++ b/libraries/src/main/resources/smooks/item-rules.csv @@ -0,0 +1 @@ +"max_total","item.quantity * item.price < 300.00" diff --git a/libraries/src/main/resources/smooks/order.ftl b/libraries/src/main/resources/smooks/order.ftl new file mode 100644 index 0000000000..9d40eb55c7 --- /dev/null +++ b/libraries/src/main/resources/smooks/order.ftl @@ -0,0 +1,7 @@ +<#setting locale="en_US"> +UNA:+.? ' +UNH+${order.number}+${order.status}+${order.creationDate?string["yyyy-MM-dd"]}' +CTA+${supplier.name}+${supplier.phoneNumber}' +<#list items as item> +LIN+${item.quantity}+${item.code}+${item.price}' + \ No newline at end of file diff --git a/libraries/src/main/resources/smooks/order.json b/libraries/src/main/resources/smooks/order.json new file mode 100644 index 0000000000..bf6bc5fe93 --- /dev/null +++ b/libraries/src/main/resources/smooks/order.json @@ -0,0 +1,21 @@ +{ + "creationDate":"2018-01-14", + "orderNumber":771, + "orderStatus":"IN_PROGRESS", + "supplier":{ + "name":"CompanyX", + "phone":"1234567" + }, + "orderItems":[ + { + "quantity":1, + "code":"PX1234", + "price":9.99 + }, + { + "quantity":2, + "code":"RX1990", + "price":120.32 + } + ] +} \ No newline at end of file diff --git a/libraries/src/main/resources/smooks/order.xml b/libraries/src/main/resources/smooks/order.xml new file mode 100644 index 0000000000..343c5cab38 --- /dev/null +++ b/libraries/src/main/resources/smooks/order.xml @@ -0,0 +1,20 @@ + + 771 + IN_PROGRESS + + CompanyX + 1234567 + + + + 1 + PX1234 + 9.99 + + + 2 + RX990 + 120.32 + + + \ No newline at end of file diff --git a/libraries/src/main/resources/smooks/smooks-mapping.xml b/libraries/src/main/resources/smooks/smooks-mapping.xml new file mode 100644 index 0000000000..7996834e38 --- /dev/null +++ b/libraries/src/main/resources/smooks/smooks-mapping.xml @@ -0,0 +1,29 @@ + + + + + + + + yyyy-MM-dd + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libraries/src/main/resources/smooks/smooks-transform-edi.xml b/libraries/src/main/resources/smooks/smooks-transform-edi.xml new file mode 100644 index 0000000000..1dae4055a8 --- /dev/null +++ b/libraries/src/main/resources/smooks/smooks-transform-edi.xml @@ -0,0 +1,11 @@ + + + + + + + /smooks/order.ftl + + + \ No newline at end of file diff --git a/libraries/src/main/resources/smooks/smooks-transform-email.xml b/libraries/src/main/resources/smooks/smooks-transform-email.xml new file mode 100644 index 0000000000..101aa67f0d --- /dev/null +++ b/libraries/src/main/resources/smooks/smooks-transform-email.xml @@ -0,0 +1,12 @@ + + + + + + + + /smooks/email.ftl + + + \ No newline at end of file diff --git a/libraries/src/main/resources/smooks/smooks-validation.xml b/libraries/src/main/resources/smooks/smooks-validation.xml new file mode 100644 index 0000000000..b66722ffc5 --- /dev/null +++ b/libraries/src/main/resources/smooks/smooks-validation.xml @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + diff --git a/libraries/src/main/resources/smooks/supplier.properties b/libraries/src/main/resources/smooks/supplier.properties new file mode 100644 index 0000000000..cc17e45eb4 --- /dev/null +++ b/libraries/src/main/resources/smooks/supplier.properties @@ -0,0 +1,2 @@ +supplierName=[A-Za-z0-9]* +supplierPhone=^[0-9\\-\\+]{9,15}$ diff --git a/libraries/src/test/java/com/baeldung/smooks/converter/SmooksIntegrationTest.java b/libraries/src/test/java/com/baeldung/smooks/converter/SmooksIntegrationTest.java new file mode 100644 index 0000000000..4d2cb71329 --- /dev/null +++ b/libraries/src/test/java/com/baeldung/smooks/converter/SmooksIntegrationTest.java @@ -0,0 +1,70 @@ +package com.baeldung.smooks.converter; + +import com.baeldung.smooks.model.Item; +import com.baeldung.smooks.model.Order; +import com.baeldung.smooks.model.Status; +import com.baeldung.smooks.model.Supplier; +import org.junit.Test; +import org.milyn.validation.ValidationResult; +import java.text.SimpleDateFormat; +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; + + +public class SmooksIntegrationTest { + + private static final String EDIFACT_MESSAGE = + "UNA:+.? '\r\n" + + "UNH+771+IN_PROGRESS+2018-01-14'\r\n" + + "CTA+CompanyX+1234567'\r\n" + + "LIN+1+PX1234+9.99'\r\n" + + "LIN+2+RX990+120.32'\r\n"; + private static final String EMAIL_MESSAGE = + "Hi,\r\n" + + "Order number #771 created on 2018-01-14 is currently in IN_PROGRESS status.\r\n" + + "Consider contact supplier \"CompanyX\" with phone number: \"1234567\".\r\n" + + "Order items:\r\n" + + "1 X PX1234 (total price 9.99)\r\n" + + "2 X RX990 (total price 240.64)\r\n"; + + @Test + public void givenOrderXML_whenConvert_thenPOJOsConstructedCorrectly() throws Exception { + + OrderConverter xmlToJavaOrderConverter = new OrderConverter(); + Order order = xmlToJavaOrderConverter.convertOrderXMLToOrderObject("/smooks/order.xml"); + + assertThat(order.getNumber(),is(771L)); + assertThat(order.getStatus(),is(Status.IN_PROGRESS)); + assertThat(order.getCreationDate(),is(new SimpleDateFormat("yyyy-MM-dd").parse("2018-01-14"))); + assertThat(order.getSupplier(),is(new Supplier("CompanyX","1234567"))); + assertThat(order.getItems(),containsInAnyOrder( + new Item("PX1234",9.99,1), + new Item("RX990",120.32,2)) + ); + + } + + @Test + public void givenIncorrectOrderXML_whenValidate_thenExpectValidationErrors() throws Exception { + OrderValidator orderValidator = new OrderValidator(); + ValidationResult validationResult = orderValidator.validate("/smooks/order.xml"); + + assertThat(validationResult.getErrors(), hasSize(1)); + // 1234567 didn't match ^[0-9\\-\\+]{9,15}$ + assertThat(validationResult.getErrors().get(0).getFailRuleResult().getRuleName(),is("supplierPhone")); + } + + @Test + public void givenOrderXML_whenApplyEDITemplate_thenConvertedToEDIFACT() throws Exception { + OrderConverter orderConverter = new OrderConverter(); + String edifact = orderConverter.convertOrderXMLtoEDIFACT("/smooks/order.xml"); + assertThat(edifact,is(EDIFACT_MESSAGE)); + } + + @Test + public void givenOrderXML_whenApplyEmailTemplate_thenConvertedToEmailMessage() throws Exception { + OrderConverter orderConverter = new OrderConverter(); + String emailMessage = orderConverter.convertOrderXMLtoEmailMessage("/smooks/order.xml"); + assertThat(emailMessage,is(EMAIL_MESSAGE)); + } +} \ No newline at end of file From eb99ad575377f17e81e0cb480bcd4d48e234204c Mon Sep 17 00:00:00 2001 From: Nam Thai Nguyen Date: Wed, 31 Jan 2018 16:32:21 +0700 Subject: [PATCH 11/28] Initial commit for BAEL-1515 --- testing-modules/testing/pom.xml | 12 ++++++ .../testing/assertj/custom/Assertions.java | 11 ++++++ .../baeldung/testing/assertj/custom/Car.java | 22 +++++++++++ .../testing/assertj/custom/CarAssert.java | 30 +++++++++++++++ .../testing/assertj/custom/Person.java | 32 ++++++++++++++++ .../testing/assertj/custom/PersonAssert.java | 38 +++++++++++++++++++ .../custom/AssertJCarAssertUnitTest.java | 20 ++++++++++ .../AssertJCustomAssertionsUnitTest.java | 29 ++++++++++++++ .../custom/AssertJPersonAssertUnitTest.java | 26 +++++++++++++ 9 files changed, 220 insertions(+) create mode 100644 testing-modules/testing/src/main/java/com/baeldung/testing/assertj/custom/Assertions.java create mode 100644 testing-modules/testing/src/main/java/com/baeldung/testing/assertj/custom/Car.java create mode 100644 testing-modules/testing/src/main/java/com/baeldung/testing/assertj/custom/CarAssert.java create mode 100644 testing-modules/testing/src/main/java/com/baeldung/testing/assertj/custom/Person.java create mode 100644 testing-modules/testing/src/main/java/com/baeldung/testing/assertj/custom/PersonAssert.java create mode 100644 testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/AssertJCarAssertUnitTest.java create mode 100644 testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/AssertJCustomAssertionsUnitTest.java create mode 100644 testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/AssertJPersonAssertUnitTest.java diff --git a/testing-modules/testing/pom.xml b/testing-modules/testing/pom.xml index 1fd6357b87..6f185d3b4c 100644 --- a/testing-modules/testing/pom.xml +++ b/testing-modules/testing/pom.xml @@ -154,6 +154,17 @@ + + org.assertj + assertj-assertions-generator-maven-plugin + ${assertj-generator.version} + + + com.baeldung.testing.assertj.custom.Person + com.baeldung.testing.assertj.custom.Car + + + @@ -164,6 +175,7 @@ 21.0 3.1.0 3.6.1 + 2.1.0 0.32 1.1.0 0.12 diff --git a/testing-modules/testing/src/main/java/com/baeldung/testing/assertj/custom/Assertions.java b/testing-modules/testing/src/main/java/com/baeldung/testing/assertj/custom/Assertions.java new file mode 100644 index 0000000000..5c72eb6d05 --- /dev/null +++ b/testing-modules/testing/src/main/java/com/baeldung/testing/assertj/custom/Assertions.java @@ -0,0 +1,11 @@ +package com.baeldung.testing.assertj.custom; + +public class Assertions { + public static PersonAssert assertThat(Person actual) { + return new PersonAssert(actual); + } + + public static CarAssert assertThat(Car actual) { + return new CarAssert(actual); + } +} diff --git a/testing-modules/testing/src/main/java/com/baeldung/testing/assertj/custom/Car.java b/testing-modules/testing/src/main/java/com/baeldung/testing/assertj/custom/Car.java new file mode 100644 index 0000000000..e52ffee8e5 --- /dev/null +++ b/testing-modules/testing/src/main/java/com/baeldung/testing/assertj/custom/Car.java @@ -0,0 +1,22 @@ +package com.baeldung.testing.assertj.custom; + +public class Car { + private String type; + private Person owner; + + public Car(String type) { + this.type = type; + } + + public String getType() { + return type; + } + + public Person getOwner() { + return owner; + } + + public void setOwner(Person owner) { + this.owner = owner; + } +} diff --git a/testing-modules/testing/src/main/java/com/baeldung/testing/assertj/custom/CarAssert.java b/testing-modules/testing/src/main/java/com/baeldung/testing/assertj/custom/CarAssert.java new file mode 100644 index 0000000000..413c2d3e12 --- /dev/null +++ b/testing-modules/testing/src/main/java/com/baeldung/testing/assertj/custom/CarAssert.java @@ -0,0 +1,30 @@ +package com.baeldung.testing.assertj.custom; + +import org.assertj.core.api.AbstractAssert; + +public class CarAssert extends AbstractAssert { + + public CarAssert(Car actual) { + super(actual, CarAssert.class); + } + + public static CarAssert assertThat(Car actual) { + return new CarAssert(actual); + } + + public CarAssert hasType(String type) { + isNotNull(); + if (!actual.getType().equals(type)) { + failWithMessage("Expected type %s but was %s", type, actual.getType()); + } + return this; + } + + public CarAssert isUsed() { + isNotNull(); + if (actual.getOwner() == null) { + failWithMessage("Expected old but was new"); + } + return this; + } +} diff --git a/testing-modules/testing/src/main/java/com/baeldung/testing/assertj/custom/Person.java b/testing-modules/testing/src/main/java/com/baeldung/testing/assertj/custom/Person.java new file mode 100644 index 0000000000..34afc480e4 --- /dev/null +++ b/testing-modules/testing/src/main/java/com/baeldung/testing/assertj/custom/Person.java @@ -0,0 +1,32 @@ +package com.baeldung.testing.assertj.custom; + +import java.util.ArrayList; +import java.util.List; + +public class Person { + private String fullName; + private int age; + private List nicknames; + + public Person(String fullName, int age) { + this.fullName = fullName; + this.age = age; + this.nicknames = new ArrayList<>(); + } + + public void addNickname(String nickname) { + nicknames.add(nickname); + } + + public String getFullName() { + return fullName; + } + + public int getAge() { + return age; + } + + public List getNicknames() { + return nicknames; + } +} diff --git a/testing-modules/testing/src/main/java/com/baeldung/testing/assertj/custom/PersonAssert.java b/testing-modules/testing/src/main/java/com/baeldung/testing/assertj/custom/PersonAssert.java new file mode 100644 index 0000000000..4c071660f3 --- /dev/null +++ b/testing-modules/testing/src/main/java/com/baeldung/testing/assertj/custom/PersonAssert.java @@ -0,0 +1,38 @@ +package com.baeldung.testing.assertj.custom; + +import org.assertj.core.api.AbstractAssert; + +public class PersonAssert extends AbstractAssert { + + public PersonAssert(Person actual) { + super(actual, PersonAssert.class); + } + + public static PersonAssert assertThat(Person actual) { + return new PersonAssert(actual); + } + + public PersonAssert hasFullName(String fullName) { + isNotNull(); + if (!actual.getFullName().equals(fullName)) { + failWithMessage("Expected full name %s but was %s", fullName, actual.getFullName()); + } + return this; + } + + public PersonAssert isAdult() { + isNotNull(); + if (actual.getAge() < 18) { + failWithMessage("Expected adult but was juvenile"); + } + return this; + } + + public PersonAssert hasNickname(String nickName) { + isNotNull(); + if (!actual.getNicknames().contains(nickName)) { + failWithMessage("Expected nickname %s but did not have", nickName); + } + return this; + } +} diff --git a/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/AssertJCarAssertUnitTest.java b/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/AssertJCarAssertUnitTest.java new file mode 100644 index 0000000000..d438cc42f6 --- /dev/null +++ b/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/AssertJCarAssertUnitTest.java @@ -0,0 +1,20 @@ +package com.baeldung.testing.assertj.custom; + +import static com.baeldung.testing.assertj.custom.CarAssert.assertThat; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +public class AssertJCarAssertUnitTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void whenCarTypeDoesNotMatch_thenIncorrect() { + thrown.expect(AssertionError.class); + thrown.expectMessage("Expected type SUV but was Sedan"); + Car car = new Car("Sedan"); + assertThat(car).hasType("SUV"); + } +} diff --git a/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/AssertJCustomAssertionsUnitTest.java b/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/AssertJCustomAssertionsUnitTest.java new file mode 100644 index 0000000000..8b800de3db --- /dev/null +++ b/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/AssertJCustomAssertionsUnitTest.java @@ -0,0 +1,29 @@ +package com.baeldung.testing.assertj.custom; + +import static com.baeldung.testing.assertj.custom.Assertions.assertThat; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +public class AssertJCustomAssertionsUnitTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void whenPersonDoesNotHaveAMatchingNickname_thenIncorrect() { + thrown.expect(AssertionError.class); + thrown.expectMessage("Expected nickname John but did not have"); + Person person = new Person("John Doe", 20); + person.addNickname("Nick"); + assertThat(person).hasNickname("John"); + } + + @Test + public void whenCarIsUsed_thenCorrect() { + Person person = new Person("Jane Roe", 16); + Car car = new Car("SUV"); + car.setOwner(person); + assertThat(car).isUsed(); + } +} diff --git a/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/AssertJPersonAssertUnitTest.java b/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/AssertJPersonAssertUnitTest.java new file mode 100644 index 0000000000..ab421915af --- /dev/null +++ b/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/AssertJPersonAssertUnitTest.java @@ -0,0 +1,26 @@ +package com.baeldung.testing.assertj.custom; + +import static com.baeldung.testing.assertj.custom.PersonAssert.assertThat; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +public class AssertJPersonAssertUnitTest { + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void whenPersonNameMatches_thenCorrect() { + Person person = new Person("John Doe", 20); + assertThat(person).hasFullName("John Doe"); + } + + @Test + public void whenPersonAgeLessThanEighteen_thenNotAdult() { + thrown.expect(AssertionError.class); + thrown.expectMessage("Expected adult but was juvenile"); + Person person = new Person("Jane Roe", 16); + assertThat(person).isAdult(); + } +} From 950434a87341b4a6f1085b8feb8bb33eb95447f2 Mon Sep 17 00:00:00 2001 From: Nam Thai Nguyen Date: Wed, 31 Jan 2018 16:46:19 +0700 Subject: [PATCH 12/28] Fix the scope of AssertJ core --- testing-modules/testing/pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/testing-modules/testing/pom.xml b/testing-modules/testing/pom.xml index 6f185d3b4c..2804a94244 100644 --- a/testing-modules/testing/pom.xml +++ b/testing-modules/testing/pom.xml @@ -34,7 +34,6 @@ org.assertj assertj-core ${assertj-core.version} - test From 5f87ceb1ffcdaf64f9d4ecf8ee468511c22a9f92 Mon Sep 17 00:00:00 2001 From: Nam Thai Nguyen Date: Wed, 31 Jan 2018 18:34:09 +0700 Subject: [PATCH 13/28] Relocate custom assertion classes --- testing-modules/testing/pom.xml | 1 + .../java/com/baeldung/testing/assertj/custom/Assertions.java | 0 .../java/com/baeldung/testing/assertj/custom/CarAssert.java | 0 .../java/com/baeldung/testing/assertj/custom/PersonAssert.java | 0 4 files changed, 1 insertion(+) rename testing-modules/testing/src/{main => test}/java/com/baeldung/testing/assertj/custom/Assertions.java (100%) rename testing-modules/testing/src/{main => test}/java/com/baeldung/testing/assertj/custom/CarAssert.java (100%) rename testing-modules/testing/src/{main => test}/java/com/baeldung/testing/assertj/custom/PersonAssert.java (100%) diff --git a/testing-modules/testing/pom.xml b/testing-modules/testing/pom.xml index 2804a94244..6f185d3b4c 100644 --- a/testing-modules/testing/pom.xml +++ b/testing-modules/testing/pom.xml @@ -34,6 +34,7 @@ org.assertj assertj-core ${assertj-core.version} + test diff --git a/testing-modules/testing/src/main/java/com/baeldung/testing/assertj/custom/Assertions.java b/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/Assertions.java similarity index 100% rename from testing-modules/testing/src/main/java/com/baeldung/testing/assertj/custom/Assertions.java rename to testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/Assertions.java diff --git a/testing-modules/testing/src/main/java/com/baeldung/testing/assertj/custom/CarAssert.java b/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/CarAssert.java similarity index 100% rename from testing-modules/testing/src/main/java/com/baeldung/testing/assertj/custom/CarAssert.java rename to testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/CarAssert.java diff --git a/testing-modules/testing/src/main/java/com/baeldung/testing/assertj/custom/PersonAssert.java b/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/PersonAssert.java similarity index 100% rename from testing-modules/testing/src/main/java/com/baeldung/testing/assertj/custom/PersonAssert.java rename to testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/PersonAssert.java From bd9a87c137477b26047f9e033e5fa6f049a534ba Mon Sep 17 00:00:00 2001 From: Aprian Diaz Novandi Date: Wed, 31 Jan 2018 15:58:52 +0100 Subject: [PATCH 14/28] Simplify unit test logic (#3548) --- .../baeldung/guava/GuavaMemoizerUnitTest.java | 60 +++++++++---------- 1 file changed, 27 insertions(+), 33 deletions(-) diff --git a/guava/src/test/java/org/baeldung/guava/GuavaMemoizerUnitTest.java b/guava/src/test/java/org/baeldung/guava/GuavaMemoizerUnitTest.java index 0ae1f438e3..1f934347b4 100644 --- a/guava/src/test/java/org/baeldung/guava/GuavaMemoizerUnitTest.java +++ b/guava/src/test/java/org/baeldung/guava/GuavaMemoizerUnitTest.java @@ -38,7 +38,7 @@ public class GuavaMemoizerUnitTest { int n = 95; // when - BigInteger factorial = new Factorial().getFactorial(n); + BigInteger factorial = Factorial.getFactorial(n); // then BigInteger expectedFactorial = new BigInteger("10329978488239059262599702099394727095397746340117372869212250571234293987594703124871765375385424468563282236864226607350415360000000000000000000000"); @@ -47,52 +47,46 @@ public class GuavaMemoizerUnitTest { @Test public void givenMemoizedSupplier_whenGet_thenSubsequentGetsAreFast() { + // given Supplier memoizedSupplier; memoizedSupplier = Suppliers.memoize(CostlySupplier::generateBigNumber); - Instant start = Instant.now(); - BigInteger bigNumber = memoizedSupplier.get(); - Long durationInMs = Duration.between(start, Instant.now()).toMillis(); - assertThat(bigNumber, is(equalTo(new BigInteger("12345")))); - assertThat(durationInMs.doubleValue(), is(closeTo(2000D, 100D))); + // when + BigInteger expectedValue = new BigInteger("12345"); + assertSupplierGetExecutionResultAndDuration(memoizedSupplier, expectedValue, 2000D); - start = Instant.now(); - bigNumber = memoizedSupplier.get().add(BigInteger.ONE); - durationInMs = Duration.between(start, Instant.now()).toMillis(); - assertThat(bigNumber, is(equalTo(new BigInteger("12346")))); - assertThat(durationInMs.doubleValue(), is(closeTo(0D, 100D))); - - start = Instant.now(); - bigNumber = memoizedSupplier.get().add(BigInteger.TEN); - durationInMs = Duration.between(start, Instant.now()).toMillis(); - assertThat(bigNumber, is(equalTo(new BigInteger("12355")))); - assertThat(durationInMs.doubleValue(), is(closeTo(0D, 100D))); + // then + assertSupplierGetExecutionResultAndDuration(memoizedSupplier, expectedValue, 0D); + assertSupplierGetExecutionResultAndDuration(memoizedSupplier, expectedValue, 0D); } @Test public void givenMemoizedSupplierWithExpiration_whenGet_thenSubsequentGetsBeforeExpiredAreFast() throws InterruptedException { + // given Supplier memoizedSupplier; memoizedSupplier = Suppliers.memoizeWithExpiration(CostlySupplier::generateBigNumber, 3, TimeUnit.SECONDS); - Instant start = Instant.now(); - BigInteger bigNumber = memoizedSupplier.get(); - Long durationInMs = Duration.between(start, Instant.now()).toMillis(); - assertThat(bigNumber, is(equalTo(new BigInteger("12345")))); - assertThat(durationInMs.doubleValue(), is(closeTo(2000D, 100D))); - - start = Instant.now(); - bigNumber = memoizedSupplier.get().add(BigInteger.ONE); - durationInMs = Duration.between(start, Instant.now()).toMillis(); - assertThat(bigNumber, is(equalTo(new BigInteger("12346")))); - assertThat(durationInMs.doubleValue(), is(closeTo(0D, 100D))); + // when + BigInteger expectedValue = new BigInteger("12345"); + assertSupplierGetExecutionResultAndDuration(memoizedSupplier, expectedValue, 2000D); + // then + assertSupplierGetExecutionResultAndDuration(memoizedSupplier, expectedValue, 0D); + // add one more second until memoized Supplier is evicted from memory TimeUnit.SECONDS.sleep(1); + assertSupplierGetExecutionResultAndDuration(memoizedSupplier, expectedValue, 2000D); + } - start = Instant.now(); - bigNumber = memoizedSupplier.get().add(BigInteger.TEN); - durationInMs = Duration.between(start, Instant.now()).toMillis(); - assertThat(bigNumber, is(equalTo(new BigInteger("12355")))); - assertThat(durationInMs.doubleValue(), is(closeTo(2000D, 100D))); + private void assertSupplierGetExecutionResultAndDuration(Supplier supplier, + T expectedValue, + double expectedDurationInMs) { + Instant start = Instant.now(); + T value = supplier.get(); + Long durationInMs = Duration.between(start, Instant.now()).toMillis(); + double marginOfErrorInMs = 100D; + + assertThat(value, is(equalTo(expectedValue))); + assertThat(durationInMs.doubleValue(), is(closeTo(expectedDurationInMs, marginOfErrorInMs))); } } From 43a4d08c363242fd565f2f5cc3c03456b8a1b95d Mon Sep 17 00:00:00 2001 From: Grzegorz Piwowarek Date: Wed, 31 Jan 2018 18:50:37 +0100 Subject: [PATCH 15/28] Sudoku refactor (#3556) * BacktrackingAlgorithm refactor * DancingLinks refactor --- .../sudoku/BacktrackingAlgorithm.java | 79 ++++++++++--------- .../algorithms/sudoku/ColumnNode.java | 2 +- .../algorithms/sudoku/DancingLinks.java | 23 +++--- .../sudoku/DancingLinksAlgorithm.java | 46 ++++++----- .../algorithms/sudoku/DancingNode.java | 4 +- 5 files changed, 76 insertions(+), 78 deletions(-) diff --git a/algorithms/src/main/java/com/baeldung/algorithms/sudoku/BacktrackingAlgorithm.java b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/BacktrackingAlgorithm.java index 127e78900c..dc2a324c12 100644 --- a/algorithms/src/main/java/com/baeldung/algorithms/sudoku/BacktrackingAlgorithm.java +++ b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/BacktrackingAlgorithm.java @@ -3,25 +3,25 @@ package com.baeldung.algorithms.sudoku; import java.util.stream.IntStream; public class BacktrackingAlgorithm { - - private static int BOARD_SIZE = 9; - private static int SUBSECTION_SIZE = 3; - private static int BOARD_START_INDEX = 0; - - private static int NO_VALUE = 0; - private static int MIN_VALUE = 1; - private static int MAX_VALUE = 9; - public static int[][] board = { - { 8, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 3, 6, 0, 0, 0, 0, 0 }, - { 0, 7, 0, 0, 9, 0, 2, 0, 0 }, - { 0, 5, 0, 0, 0, 7, 0, 0, 0 }, - { 0, 0, 0, 0, 4, 5, 7, 0, 0 }, - { 0, 0, 0, 1, 0, 0, 0, 3, 0 }, - { 0, 0, 1, 0, 0, 0, 0, 6, 8 }, - { 0, 0, 8, 5, 0, 0, 0, 1, 0 }, - { 0, 9, 0, 0, 0, 0, 4, 0, 0 } + private static final int BOARD_SIZE = 9; + private static final int SUBSECTION_SIZE = 3; + private static final int BOARD_START_INDEX = 0; + + private static final int NO_VALUE = 0; + private static final int MIN_VALUE = 1; + private static final int MAX_VALUE = 9; + + private static int[][] board = { + {8, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 3, 6, 0, 0, 0, 0, 0}, + {0, 7, 0, 0, 9, 0, 2, 0, 0}, + {0, 5, 0, 0, 0, 7, 0, 0, 0}, + {0, 0, 0, 0, 4, 5, 7, 0, 0}, + {0, 0, 0, 1, 0, 0, 0, 3, 0}, + {0, 0, 1, 0, 0, 0, 0, 6, 8}, + {0, 0, 8, 5, 0, 0, 0, 1, 0}, + {0, 9, 0, 0, 0, 0, 4, 0, 0} }; public static void main(String[] args) { @@ -30,7 +30,7 @@ public class BacktrackingAlgorithm { solver.printBoard(); } - public void printBoard() { + private void printBoard() { for (int row = BOARD_START_INDEX; row < BOARD_SIZE; row++) { for (int column = BOARD_START_INDEX; column < BOARD_SIZE; column++) { System.out.print(board[row][column] + " "); @@ -39,7 +39,7 @@ public class BacktrackingAlgorithm { } } - public boolean solve(int[][] board) { + private boolean solve(int[][] board) { for (int r = BOARD_START_INDEX; r < BOARD_SIZE; r++) { for (int c = BOARD_START_INDEX; c < BOARD_SIZE; c++) { if (board[r][c] == NO_VALUE) { @@ -47,9 +47,8 @@ public class BacktrackingAlgorithm { board[r][c] = k; if (isValid(board, r, c) && solve(board)) { return true; - } else { - board[r][c] = NO_VALUE; } + board[r][c] = NO_VALUE; } return false; } @@ -58,16 +57,22 @@ public class BacktrackingAlgorithm { return true; } - public boolean isValid(int[][] board, int r, int c) { - return (rowConstraint(board, r) && - columnConstraint(board, c) && - subsectionConstraint(board, r, c)); + private boolean isValid(int[][] board, int r, int c) { + return rowConstraint(board, r) && + columnConstraint(board, c) && + subsectionConstraint(board, r, c); } private boolean subsectionConstraint(int[][] board, int r, int c) { boolean[] constraint = new boolean[BOARD_SIZE]; - for (int i = (r / SUBSECTION_SIZE) * SUBSECTION_SIZE; i < (r / SUBSECTION_SIZE) * SUBSECTION_SIZE + SUBSECTION_SIZE; i++) { - for (int j = (c / SUBSECTION_SIZE) * SUBSECTION_SIZE; j < (c / SUBSECTION_SIZE) * SUBSECTION_SIZE + SUBSECTION_SIZE; j++) { + int subsectionRowStart = (r / SUBSECTION_SIZE) * SUBSECTION_SIZE; + int subsectionRowEnd = subsectionRowStart + SUBSECTION_SIZE; + + int subsectionColumnStart = (c / SUBSECTION_SIZE) * SUBSECTION_SIZE; + int subsectionColumnEnd = subsectionColumnStart + SUBSECTION_SIZE; + + for (int i = subsectionRowStart; i < subsectionRowEnd; i++) { + for (int j = subsectionColumnStart; j < subsectionColumnEnd; j++) { if (!checkConstraint(board, i, constraint, j)) return false; } } @@ -76,23 +81,19 @@ public class BacktrackingAlgorithm { private boolean columnConstraint(int[][] board, int c) { boolean[] constraint = new boolean[BOARD_SIZE]; - for (int i = BOARD_START_INDEX; i < BOARD_SIZE; i++) { - if (!checkConstraint(board, i, constraint, c)) return false; - } - return true; + return IntStream.range(BOARD_START_INDEX, BOARD_SIZE) + .allMatch(i -> checkConstraint(board, i, constraint, c)); } private boolean rowConstraint(int[][] board, int r) { boolean[] constraint = new boolean[BOARD_SIZE]; - for (int i = BOARD_START_INDEX; i < BOARD_SIZE; i++) { - if (!checkConstraint(board, r, constraint, i)) return false; - } - return true; + return IntStream.range(BOARD_START_INDEX, BOARD_SIZE) + .allMatch(i -> checkConstraint(board, r, constraint, i)); } private boolean checkConstraint(int[][] board, int r, boolean[] constraint, int c) { - if (board[r][c] >= MIN_VALUE && board[r][c] <= MAX_VALUE) { - if (constraint[board[r][c] - 1] == false) { + if (board[r][c] != NO_VALUE) { + if (!constraint[board[r][c] - 1]) { constraint[board[r][c] - 1] = true; } else { return false; @@ -100,4 +101,4 @@ public class BacktrackingAlgorithm { } return true; } -} +} \ No newline at end of file diff --git a/algorithms/src/main/java/com/baeldung/algorithms/sudoku/ColumnNode.java b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/ColumnNode.java index 48538344b6..46995ca42f 100644 --- a/algorithms/src/main/java/com/baeldung/algorithms/sudoku/ColumnNode.java +++ b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/ColumnNode.java @@ -4,7 +4,7 @@ class ColumnNode extends DancingNode { int size; String name; - public ColumnNode(String n) { + ColumnNode(String n) { super(); size = 0; name = n; diff --git a/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingLinks.java b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingLinks.java index a30f8ecab5..e5a02b7c91 100644 --- a/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingLinks.java +++ b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingLinks.java @@ -50,10 +50,9 @@ public class DancingLinks { private ColumnNode makeDLXBoard(boolean[][] grid) { final int COLS = grid[0].length; - final int ROWS = grid.length; ColumnNode headerNode = new ColumnNode("header"); - ArrayList columnNodes = new ArrayList(); + List columnNodes = new ArrayList<>(); for (int i = 0; i < COLS; i++) { ColumnNode n = new ColumnNode(Integer.toString(i)); @@ -62,10 +61,10 @@ public class DancingLinks { } headerNode = headerNode.R.C; - for (int i = 0; i < ROWS; i++) { + for (boolean[] aGrid : grid) { DancingNode prev = null; for (int j = 0; j < COLS; j++) { - if (grid[i][j] == true) { + if (aGrid[j]) { ColumnNode col = columnNodes.get(j); DancingNode newNode = new DancingNode(col); if (prev == null) @@ -82,21 +81,21 @@ public class DancingLinks { return headerNode; } - public DancingLinks(boolean[][] cover) { + DancingLinks(boolean[][] cover) { header = makeDLXBoard(cover); } public void runSolver() { - answer = new LinkedList(); + answer = new LinkedList<>(); search(0); } - public void handleSolution(List answer) { + private void handleSolution(List answer) { int[][] result = parseBoard(answer); printSolution(result); } - int size = 9; + private int size = 9; private int[][] parseBoard(List answer) { int[][] result = new int[size][size]; @@ -120,12 +119,12 @@ public class DancingLinks { return result; } - public static void printSolution(int[][] result) { + private static void printSolution(int[][] result) { int N = result.length; - for (int i = 0; i < N; i++) { - String ret = ""; + for (int[] aResult : result) { + StringBuilder ret = new StringBuilder(); for (int j = 0; j < N; j++) { - ret += result[i][j] + " "; + ret.append(aResult[j]).append(" "); } System.out.println(ret); } diff --git a/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingLinksAlgorithm.java b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingLinksAlgorithm.java index 057a15c594..6b0f57a075 100644 --- a/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingLinksAlgorithm.java +++ b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingLinksAlgorithm.java @@ -1,39 +1,37 @@ package com.baeldung.algorithms.sudoku; -import java.util.*; +import java.util.Arrays; public class DancingLinksAlgorithm { - private static int BOARD_SIZE = 9; - private static int SUBSECTION_SIZE = 3; - private static int NO_VALUE = 0; - private static int CONSTRAINTS = 4; - private static int MIN_VALUE = 1; - private static int MAX_VALUE = 9; - private static int COVER_START_INDEX = 1; + private static final int BOARD_SIZE = 9; + private static final int SUBSECTION_SIZE = 3; + private static final int NO_VALUE = 0; + private static final int CONSTRAINTS = 4; + private static final int MIN_VALUE = 1; + private static final int MAX_VALUE = 9; + private static final int COVER_START_INDEX = 1; - public static int[][] board = { - { 8, 0, 0, 0, 0, 0, 0, 0, 0 }, - { 0, 0, 3, 6, 0, 0, 0, 0, 0 }, - { 0, 7, 0, 0, 9, 0, 2, 0, 0 }, - { 0, 5, 0, 0, 0, 7, 0, 0, 0 }, - { 0, 0, 0, 0, 4, 5, 7, 0, 0 }, - { 0, 0, 0, 1, 0, 0, 0, 3, 0 }, - { 0, 0, 1, 0, 0, 0, 0, 6, 8 }, - { 0, 0, 8, 5, 0, 0, 0, 1, 0 }, - { 0, 9, 0, 0, 0, 0, 4, 0, 0 } - }; + private static int[][] board = { + {8, 0, 0, 0, 0, 0, 0, 0, 0}, + {0, 0, 3, 6, 0, 0, 0, 0, 0}, + {0, 7, 0, 0, 9, 0, 2, 0, 0}, + {0, 5, 0, 0, 0, 7, 0, 0, 0}, + {0, 0, 0, 0, 4, 5, 7, 0, 0}, + {0, 0, 0, 1, 0, 0, 0, 3, 0}, + {0, 0, 1, 0, 0, 0, 0, 6, 8}, + {0, 0, 8, 5, 0, 0, 0, 1, 0}, + {0, 9, 0, 0, 0, 0, 4, 0, 0} + }; public static void main(String[] args) { DancingLinksAlgorithm solver = new DancingLinksAlgorithm(); solver.solve(board); } - public boolean solve(int[][] board) { + private void solve(int[][] board) { boolean[][] cover = initializeExactCoverBoard(board); DancingLinks dlx = new DancingLinks(cover); dlx.runSolver(); - - return true; } private int getIndex(int row, int col, int num) { @@ -54,7 +52,7 @@ public class DancingLinksAlgorithm { } } } - + // Row constrain. for (int r = COVER_START_INDEX; r <= BOARD_SIZE; r++) { for (int n = COVER_START_INDEX; n <= BOARD_SIZE; n++, hBase++) { @@ -74,7 +72,7 @@ public class DancingLinksAlgorithm { } } } - + // Subsection constraint for (int br = COVER_START_INDEX; br <= BOARD_SIZE; br += SUBSECTION_SIZE) { for (int bc = COVER_START_INDEX; bc <= BOARD_SIZE; bc += SUBSECTION_SIZE) { diff --git a/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingNode.java b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingNode.java index 13dc3f2b57..b494eba9ef 100644 --- a/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingNode.java +++ b/algorithms/src/main/java/com/baeldung/algorithms/sudoku/DancingNode.java @@ -39,11 +39,11 @@ class DancingNode { this.U.D = this.D.U = this; } - public DancingNode() { + DancingNode() { L = R = U = D = this; } - public DancingNode(ColumnNode c) { + DancingNode(ColumnNode c) { this(); C = c; } From 3e4b6df194059c0fc95c22e7fe2bcf07ea6c1224 Mon Sep 17 00:00:00 2001 From: ramansahasi Date: Thu, 1 Feb 2018 02:36:16 +0530 Subject: [PATCH 16/28] Interrupted thread before logging (#3563) --- .../main/java/com/baeldung/concurrent/waitandnotify/Data.java | 4 ++-- .../java/com/baeldung/concurrent/waitandnotify/Receiver.java | 1 + .../java/com/baeldung/concurrent/waitandnotify/Sender.java | 1 + .../concurrent/waitandnotify/NetworkIntegrationTest.java | 3 ++- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/waitandnotify/Data.java b/core-java-concurrency/src/main/java/com/baeldung/concurrent/waitandnotify/Data.java index d9e7434e0c..9d76c1fcd1 100644 --- a/core-java-concurrency/src/main/java/com/baeldung/concurrent/waitandnotify/Data.java +++ b/core-java-concurrency/src/main/java/com/baeldung/concurrent/waitandnotify/Data.java @@ -1,7 +1,5 @@ package com.baeldung.concurrent.waitandnotify; -import org.slf4j.Logger; - public class Data { private String packet; @@ -14,6 +12,7 @@ public class Data { try { wait(); } catch (InterruptedException e) { + Thread.currentThread().interrupt(); System.out.println("Thread Interrupted"); } } @@ -28,6 +27,7 @@ public class Data { try { wait(); } catch (InterruptedException e) { + Thread.currentThread().interrupt(); System.out.println("Thread Interrupted"); } } diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/waitandnotify/Receiver.java b/core-java-concurrency/src/main/java/com/baeldung/concurrent/waitandnotify/Receiver.java index 724e908a99..21ba822bfd 100644 --- a/core-java-concurrency/src/main/java/com/baeldung/concurrent/waitandnotify/Receiver.java +++ b/core-java-concurrency/src/main/java/com/baeldung/concurrent/waitandnotify/Receiver.java @@ -20,6 +20,7 @@ public class Receiver implements Runnable { try { Thread.sleep(ThreadLocalRandom.current().nextInt(1000, 5000)); } catch (InterruptedException e) { + Thread.currentThread().interrupt(); System.out.println("Thread Interrupted"); } } diff --git a/core-java-concurrency/src/main/java/com/baeldung/concurrent/waitandnotify/Sender.java b/core-java-concurrency/src/main/java/com/baeldung/concurrent/waitandnotify/Sender.java index b4945b7b73..c365294cdd 100644 --- a/core-java-concurrency/src/main/java/com/baeldung/concurrent/waitandnotify/Sender.java +++ b/core-java-concurrency/src/main/java/com/baeldung/concurrent/waitandnotify/Sender.java @@ -25,6 +25,7 @@ public class Sender implements Runnable { try { Thread.sleep(ThreadLocalRandom.current().nextInt(1000, 5000)); } catch (InterruptedException e) { + Thread.currentThread().interrupt(); System.out.println("Thread Interrupted"); } } diff --git a/core-java-concurrency/src/test/java/com/baeldung/concurrent/waitandnotify/NetworkIntegrationTest.java b/core-java-concurrency/src/test/java/com/baeldung/concurrent/waitandnotify/NetworkIntegrationTest.java index 8ecc92236e..e2bc328df3 100644 --- a/core-java-concurrency/src/test/java/com/baeldung/concurrent/waitandnotify/NetworkIntegrationTest.java +++ b/core-java-concurrency/src/test/java/com/baeldung/concurrent/waitandnotify/NetworkIntegrationTest.java @@ -57,7 +57,8 @@ public class NetworkIntegrationTest { sender.join(); receiver.join(); } catch (InterruptedException e) { - e.printStackTrace(); + Thread.currentThread().interrupt(); + System.out.println("Thread Interrupted"); } assertEquals(expected, outContent.toString()); From 63b8aa334f89ab042e4203f99d032b03a1dd8b60 Mon Sep 17 00:00:00 2001 From: Nam Thai Nguyen Date: Thu, 1 Feb 2018 11:00:51 +0700 Subject: [PATCH 17/28] Refactor BAEL-1515 --- testing-modules/testing/pom.xml | 1 - .../custom/AssertJCarAssertUnitTest.java | 20 ----------- .../AssertJCustomAssertionsUnitTest.java | 35 +++++++++++++------ .../custom/AssertJPersonAssertUnitTest.java | 26 -------------- .../testing/assertj/custom/Assertions.java | 4 +-- .../testing/assertj/custom/CarAssert.java | 30 ---------------- 6 files changed, 26 insertions(+), 90 deletions(-) delete mode 100644 testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/AssertJCarAssertUnitTest.java delete mode 100644 testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/AssertJPersonAssertUnitTest.java delete mode 100644 testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/CarAssert.java diff --git a/testing-modules/testing/pom.xml b/testing-modules/testing/pom.xml index 6f185d3b4c..c76045380b 100644 --- a/testing-modules/testing/pom.xml +++ b/testing-modules/testing/pom.xml @@ -161,7 +161,6 @@ com.baeldung.testing.assertj.custom.Person - com.baeldung.testing.assertj.custom.Car diff --git a/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/AssertJCarAssertUnitTest.java b/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/AssertJCarAssertUnitTest.java deleted file mode 100644 index d438cc42f6..0000000000 --- a/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/AssertJCarAssertUnitTest.java +++ /dev/null @@ -1,20 +0,0 @@ -package com.baeldung.testing.assertj.custom; - -import static com.baeldung.testing.assertj.custom.CarAssert.assertThat; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -public class AssertJCarAssertUnitTest { - @Rule - public ExpectedException thrown = ExpectedException.none(); - - @Test - public void whenCarTypeDoesNotMatch_thenIncorrect() { - thrown.expect(AssertionError.class); - thrown.expectMessage("Expected type SUV but was Sedan"); - Car car = new Car("Sedan"); - assertThat(car).hasType("SUV"); - } -} diff --git a/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/AssertJCustomAssertionsUnitTest.java b/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/AssertJCustomAssertionsUnitTest.java index 8b800de3db..f9b5bad039 100644 --- a/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/AssertJCustomAssertionsUnitTest.java +++ b/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/AssertJCustomAssertionsUnitTest.java @@ -1,6 +1,7 @@ package com.baeldung.testing.assertj.custom; import static com.baeldung.testing.assertj.custom.Assertions.assertThat; +import static org.junit.Assert.fail; import org.junit.Rule; import org.junit.Test; @@ -9,21 +10,35 @@ import org.junit.rules.ExpectedException; public class AssertJCustomAssertionsUnitTest { @Rule public ExpectedException thrown = ExpectedException.none(); - + @Test - public void whenPersonDoesNotHaveAMatchingNickname_thenIncorrect() { - thrown.expect(AssertionError.class); - thrown.expectMessage("Expected nickname John but did not have"); + public void whenPersonNameMatches_thenCorrect() { Person person = new Person("John Doe", 20); - person.addNickname("Nick"); - assertThat(person).hasNickname("John"); + assertThat(person).hasFullName("John Doe"); } @Test - public void whenCarIsUsed_thenCorrect() { + public void whenPersonAgeLessThanEighteen_thenNotAdult() { Person person = new Person("Jane Roe", 16); - Car car = new Car("SUV"); - car.setOwner(person); - assertThat(car).isUsed(); + + try { + assertThat(person).isAdult(); + fail(); + } catch (AssertionError e) { + org.assertj.core.api.Assertions.assertThat(e).hasMessage("Expected adult but was juvenile"); + } + } + + @Test + public void whenPersonDoesNotHaveAMatchingNickname_thenIncorrect() { + Person person = new Person("John Doe", 20); + person.addNickname("Nick"); + + try { + assertThat(person).hasNickname("John"); + fail(); + } catch (AssertionError e) { + org.assertj.core.api.Assertions.assertThat(e).hasMessage("Expected nickname John but did not have"); + } } } diff --git a/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/AssertJPersonAssertUnitTest.java b/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/AssertJPersonAssertUnitTest.java deleted file mode 100644 index ab421915af..0000000000 --- a/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/AssertJPersonAssertUnitTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package com.baeldung.testing.assertj.custom; - -import static com.baeldung.testing.assertj.custom.PersonAssert.assertThat; - -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -public class AssertJPersonAssertUnitTest { - @Rule - public ExpectedException thrown = ExpectedException.none(); - - @Test - public void whenPersonNameMatches_thenCorrect() { - Person person = new Person("John Doe", 20); - assertThat(person).hasFullName("John Doe"); - } - - @Test - public void whenPersonAgeLessThanEighteen_thenNotAdult() { - thrown.expect(AssertionError.class); - thrown.expectMessage("Expected adult but was juvenile"); - Person person = new Person("Jane Roe", 16); - assertThat(person).isAdult(); - } -} diff --git a/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/Assertions.java b/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/Assertions.java index 5c72eb6d05..fcffb8fc6c 100644 --- a/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/Assertions.java +++ b/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/Assertions.java @@ -5,7 +5,5 @@ public class Assertions { return new PersonAssert(actual); } - public static CarAssert assertThat(Car actual) { - return new CarAssert(actual); - } + // static factory methods of other assertion classes } diff --git a/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/CarAssert.java b/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/CarAssert.java deleted file mode 100644 index 413c2d3e12..0000000000 --- a/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/CarAssert.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.baeldung.testing.assertj.custom; - -import org.assertj.core.api.AbstractAssert; - -public class CarAssert extends AbstractAssert { - - public CarAssert(Car actual) { - super(actual, CarAssert.class); - } - - public static CarAssert assertThat(Car actual) { - return new CarAssert(actual); - } - - public CarAssert hasType(String type) { - isNotNull(); - if (!actual.getType().equals(type)) { - failWithMessage("Expected type %s but was %s", type, actual.getType()); - } - return this; - } - - public CarAssert isUsed() { - isNotNull(); - if (actual.getOwner() == null) { - failWithMessage("Expected old but was new"); - } - return this; - } -} From 15f18bbb83a7472328225851f527db78f938c771 Mon Sep 17 00:00:00 2001 From: ramansahasi Date: Thu, 1 Feb 2018 15:27:48 +0530 Subject: [PATCH 18/28] BAEL 1269 Intro to JSON-JAVA (#3493) * Final commit * Made changes as per last review * Moved from core-java to json module --- json/pom.xml | 5 ++ .../java/com/baeldung/jsonjava/CDLDemo.java | 59 +++++++++++++++++++ .../com/baeldung/jsonjava/CookieDemo.java | 30 ++++++++++ .../java/com/baeldung/jsonjava/DemoBean.java | 26 ++++++++ .../java/com/baeldung/jsonjava/HTTPDemo.java | 27 +++++++++ .../com/baeldung/jsonjava/JSONArrayDemo.java | 52 ++++++++++++++++ .../com/baeldung/jsonjava/JSONObjectDemo.java | 59 +++++++++++++++++++ .../baeldung/jsonjava/JSONTokenerDemo.java | 13 ++++ .../baeldung/jsonjava/CDLIntegrationTest.java | 52 ++++++++++++++++ .../jsonjava/CookieIntegrationTest.java | 29 +++++++++ .../jsonjava/HTTPIntegrationTest.java | 25 ++++++++ .../jsonjava/JSONArrayIntegrationTest.java | 47 +++++++++++++++ .../jsonjava/JSONObjectIntegrationTest.java | 53 +++++++++++++++++ .../jsonjava/JSONTokenerIntegrationTest.java | 21 +++++++ 14 files changed, 498 insertions(+) create mode 100644 json/src/main/java/com/baeldung/jsonjava/CDLDemo.java create mode 100644 json/src/main/java/com/baeldung/jsonjava/CookieDemo.java create mode 100644 json/src/main/java/com/baeldung/jsonjava/DemoBean.java create mode 100644 json/src/main/java/com/baeldung/jsonjava/HTTPDemo.java create mode 100644 json/src/main/java/com/baeldung/jsonjava/JSONArrayDemo.java create mode 100644 json/src/main/java/com/baeldung/jsonjava/JSONObjectDemo.java create mode 100644 json/src/main/java/com/baeldung/jsonjava/JSONTokenerDemo.java create mode 100644 json/src/test/java/com/baeldung/jsonjava/CDLIntegrationTest.java create mode 100644 json/src/test/java/com/baeldung/jsonjava/CookieIntegrationTest.java create mode 100644 json/src/test/java/com/baeldung/jsonjava/HTTPIntegrationTest.java create mode 100644 json/src/test/java/com/baeldung/jsonjava/JSONArrayIntegrationTest.java create mode 100644 json/src/test/java/com/baeldung/jsonjava/JSONObjectIntegrationTest.java create mode 100644 json/src/test/java/com/baeldung/jsonjava/JSONTokenerIntegrationTest.java diff --git a/json/pom.xml b/json/pom.xml index 958dd32f53..7c74d425af 100644 --- a/json/pom.xml +++ b/json/pom.xml @@ -31,6 +31,11 @@ ${fastjson.version} + + org.json + json + 20171018 + diff --git a/json/src/main/java/com/baeldung/jsonjava/CDLDemo.java b/json/src/main/java/com/baeldung/jsonjava/CDLDemo.java new file mode 100644 index 0000000000..f5fee0c4a9 --- /dev/null +++ b/json/src/main/java/com/baeldung/jsonjava/CDLDemo.java @@ -0,0 +1,59 @@ +package com.baeldung.jsonjava; + +import org.json.CDL; +import org.json.JSONArray; +import org.json.JSONTokener; + +public class CDLDemo { + public static void main(String[] args) { + System.out.println("7.1. Producing JSONArray Directly from Comma Delimited Text: "); + jsonArrayFromCDT(); + + System.out.println("\n7.2. Producing Comma Delimited Text from JSONArray: "); + cDTfromJSONArray(); + + System.out.println("\n7.3.1. Producing JSONArray of JSONObjects Using Comma Delimited Text: "); + jaOfJOFromCDT2(); + + System.out.println("\n7.3.2. Producing JSONArray of JSONObjects Using Comma Delimited Text: "); + jaOfJOFromCDT2(); + } + + public static void jsonArrayFromCDT() { + JSONArray ja = CDL.rowToJSONArray(new JSONTokener("England, USA, Canada")); + System.out.println(ja); + } + + public static void cDTfromJSONArray() { + JSONArray ja = new JSONArray("[\"England\",\"USA\",\"Canada\"]"); + String cdt = CDL.rowToString(ja); + System.out.println(cdt); + } + + public static void jaOfJOFromCDT() { + String string = + "name, city, age \n" + + "john, chicago, 22 \n" + + "gary, florida, 35 \n" + + "sal, vegas, 18"; + + JSONArray result = CDL.toJSONArray(string); + System.out.println(result.toString()); + } + + public static void jaOfJOFromCDT2() { + JSONArray ja = new JSONArray(); + ja.put("name"); + ja.put("city"); + ja.put("age"); + + String string = + "john, chicago, 22 \n" + + "gary, florida, 35 \n" + + "sal, vegas, 18"; + + JSONArray result = CDL.toJSONArray(ja, string); + System.out.println(result.toString()); + } + +} diff --git a/json/src/main/java/com/baeldung/jsonjava/CookieDemo.java b/json/src/main/java/com/baeldung/jsonjava/CookieDemo.java new file mode 100644 index 0000000000..bc39d13642 --- /dev/null +++ b/json/src/main/java/com/baeldung/jsonjava/CookieDemo.java @@ -0,0 +1,30 @@ +package com.baeldung.jsonjava; + +import org.json.Cookie; +import org.json.JSONObject; + +public class CookieDemo { + public static void main(String[] args) { + System.out.println("8.1. Converting a Cookie String into a JSONObject"); + cookieStringToJSONObject(); + + System.out.println("\n8.2. Converting a JSONObject into Cookie String"); + jSONObjectToCookieString(); + } + + public static void cookieStringToJSONObject() { + String cookie = "username=John Doe; expires=Thu, 18 Dec 2013 12:00:00 UTC; path=/"; + JSONObject cookieJO = Cookie.toJSONObject(cookie); + System.out.println(cookieJO); + } + + public static void jSONObjectToCookieString() { + JSONObject cookieJO = new JSONObject(); + cookieJO.put("name", "username"); + cookieJO.put("value", "John Doe"); + cookieJO.put("expires", "Thu, 18 Dec 2013 12:00:00 UTC"); + cookieJO.put("path", "/"); + String cookie = Cookie.toString(cookieJO); + System.out.println(cookie); + } +} diff --git a/json/src/main/java/com/baeldung/jsonjava/DemoBean.java b/json/src/main/java/com/baeldung/jsonjava/DemoBean.java new file mode 100644 index 0000000000..6d27b329c2 --- /dev/null +++ b/json/src/main/java/com/baeldung/jsonjava/DemoBean.java @@ -0,0 +1,26 @@ +package com.baeldung.jsonjava; + +public class DemoBean { + private int id; + private String name; + private boolean active; + + 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; + } + public boolean isActive() { + return active; + } + public void setActive(boolean active) { + this.active = active; + } +} diff --git a/json/src/main/java/com/baeldung/jsonjava/HTTPDemo.java b/json/src/main/java/com/baeldung/jsonjava/HTTPDemo.java new file mode 100644 index 0000000000..800018005c --- /dev/null +++ b/json/src/main/java/com/baeldung/jsonjava/HTTPDemo.java @@ -0,0 +1,27 @@ +package com.baeldung.jsonjava; + +import org.json.HTTP; +import org.json.JSONObject; + +public class HTTPDemo { + public static void main(String[] args) { + System.out.println("9.1. Converting JSONObject to HTTP Header: "); + jSONObjectToHTTPHeader(); + + System.out.println("\n9.2. Converting HTTP Header String Back to JSONObject: "); + hTTPHeaderToJSONObject(); + } + + public static void jSONObjectToHTTPHeader() { + JSONObject jo = new JSONObject(); + jo.put("Method", "POST"); + jo.put("Request-URI", "http://www.example.com/"); + jo.put("HTTP-Version", "HTTP/1.1"); + System.out.println(HTTP.toString(jo)); + } + + public static void hTTPHeaderToJSONObject() { + JSONObject obj = HTTP.toJSONObject("POST \"http://www.example.com/\" HTTP/1.1"); + System.out.println(obj); + } +} diff --git a/json/src/main/java/com/baeldung/jsonjava/JSONArrayDemo.java b/json/src/main/java/com/baeldung/jsonjava/JSONArrayDemo.java new file mode 100644 index 0000000000..2a4fab2eab --- /dev/null +++ b/json/src/main/java/com/baeldung/jsonjava/JSONArrayDemo.java @@ -0,0 +1,52 @@ +package com.baeldung.jsonjava; + +import java.util.ArrayList; +import java.util.List; + +import org.json.JSONArray; +import org.json.JSONObject; + +public class JSONArrayDemo { + public static void main(String[] args) { + System.out.println("5.1. Creating JSON Array: "); + creatingJSONArray(); + + System.out.println("\n5.2. Creating JSON Array from JSON string: "); + jsonArrayFromJSONString(); + + System.out.println("\n5.3. Creating JSON Array from Collection Object: "); + jsonArrayFromCollectionObj(); + } + + public static void creatingJSONArray() { + JSONArray ja = new JSONArray(); + ja.put(Boolean.TRUE); + ja.put("lorem ipsum"); + + // We can also put a JSONObject in JSONArray + JSONObject jo = new JSONObject(); + jo.put("name", "jon doe"); + jo.put("age", "22"); + jo.put("city", "chicago"); + + ja.put(jo); + + System.out.println(ja.toString()); + } + + public static void jsonArrayFromJSONString() { + JSONArray ja = new JSONArray("[true, \"lorem ipsum\", 215]"); + System.out.println(ja); + } + + public static void jsonArrayFromCollectionObj() { + List list = new ArrayList<>(); + list.add("California"); + list.add("Texas"); + list.add("Hawaii"); + list.add("Alaska"); + + JSONArray ja = new JSONArray(list); + System.out.println(ja); + } +} \ No newline at end of file diff --git a/json/src/main/java/com/baeldung/jsonjava/JSONObjectDemo.java b/json/src/main/java/com/baeldung/jsonjava/JSONObjectDemo.java new file mode 100644 index 0000000000..cfe8467c30 --- /dev/null +++ b/json/src/main/java/com/baeldung/jsonjava/JSONObjectDemo.java @@ -0,0 +1,59 @@ +package com.baeldung.jsonjava; + +import java.util.HashMap; +import java.util.Map; + +import org.json.JSONObject; + +public class JSONObjectDemo { + public static void main(String[] args) { + System.out.println("4.1. Creating JSONObject: "); + jsonFromJSONObject(); + + System.out.println("\n4.2. Creating JSONObject from Map: "); + jsonFromMap(); + + System.out.println("\n4.3. Creating JSONObject from JSON string: "); + jsonFromJSONString(); + + System.out.println("\n4.4. Creating JSONObject from Java Bean: "); + jsonFromDemoBean(); + } + + public static void jsonFromJSONObject() { + JSONObject jo = new JSONObject(); + jo.put("name", "jon doe"); + jo.put("age", "22"); + jo.put("city", "chicago"); + + System.out.println(jo.toString()); + } + + public static void jsonFromMap() { + Map map = new HashMap<>(); + map.put("name", "jon doe"); + map.put("age", "22"); + map.put("city", "chicago"); + JSONObject jo = new JSONObject(map); + + System.out.println(jo.toString()); + } + + public static void jsonFromJSONString() { + JSONObject jo = new JSONObject( + "{\"city\":\"chicago\",\"name\":\"jon doe\",\"age\":\"22\"}" + ); + + System.out.println(jo.toString()); + } + + public static void jsonFromDemoBean() { + DemoBean demo = new DemoBean(); + demo.setId(1); + demo.setName("lorem ipsum"); + demo.setActive(true); + + JSONObject jo = new JSONObject(demo); + System.out.println(jo); + } +} diff --git a/json/src/main/java/com/baeldung/jsonjava/JSONTokenerDemo.java b/json/src/main/java/com/baeldung/jsonjava/JSONTokenerDemo.java new file mode 100644 index 0000000000..fb9fea959c --- /dev/null +++ b/json/src/main/java/com/baeldung/jsonjava/JSONTokenerDemo.java @@ -0,0 +1,13 @@ +package com.baeldung.jsonjava; + +import org.json.JSONTokener; + +public class JSONTokenerDemo { + public static void main(String[] args) { + JSONTokener jt = new JSONTokener("Sample String"); + + while(jt.more()) { + System.out.println(jt.next()); + } + } +} diff --git a/json/src/test/java/com/baeldung/jsonjava/CDLIntegrationTest.java b/json/src/test/java/com/baeldung/jsonjava/CDLIntegrationTest.java new file mode 100644 index 0000000000..441c71e78e --- /dev/null +++ b/json/src/test/java/com/baeldung/jsonjava/CDLIntegrationTest.java @@ -0,0 +1,52 @@ +package com.baeldung.jsonjava; + +import static org.junit.Assert.assertEquals; + +import org.json.CDL; +import org.json.JSONArray; +import org.json.JSONTokener; +import org.junit.Test; + +public class CDLIntegrationTest { + @Test + public void givenCommaDelimitedText_thenConvertToJSONArray() { + JSONArray ja = CDL.rowToJSONArray(new JSONTokener("England, USA, Canada")); + assertEquals("[\"England\",\"USA\",\"Canada\"]", ja.toString()); + } + + @Test + public void givenJSONArray_thenConvertToCommaDelimitedText() { + JSONArray ja = new JSONArray("[\"England\",\"USA\",\"Canada\"]"); + String cdt = CDL.rowToString(ja); + assertEquals("England,USA,Canada", cdt.toString().trim()); + } + + @Test + public void givenCommaDelimitedText_thenGetJSONArrayOfJSONObjects() { + String string = + "name, city, age \n" + + "john, chicago, 22 \n" + + "gary, florida, 35 \n" + + "sal, vegas, 18"; + + JSONArray result = CDL.toJSONArray(string); + assertEquals("[{\"name\":\"john\",\"city\":\"chicago\",\"age\":\"22\"},{\"name\":\"gary\",\"city\":\"florida\",\"age\":\"35\"},{\"name\":\"sal\",\"city\":\"vegas\",\"age\":\"18\"}]", result.toString()); + } + + @Test + public void givenCommaDelimitedText_thenGetJSONArrayOfJSONObjects2() { + JSONArray ja = new JSONArray(); + ja.put("name"); + ja.put("city"); + ja.put("age"); + + String string = + "john, chicago, 22 \n" + + "gary, florida, 35 \n" + + "sal, vegas, 18"; + + JSONArray result = CDL.toJSONArray(ja, string); + assertEquals("[{\"name\":\"john\",\"city\":\"chicago\",\"age\":\"22\"},{\"name\":\"gary\",\"city\":\"florida\",\"age\":\"35\"},{\"name\":\"sal\",\"city\":\"vegas\",\"age\":\"18\"}]", result.toString()); + } + +} diff --git a/json/src/test/java/com/baeldung/jsonjava/CookieIntegrationTest.java b/json/src/test/java/com/baeldung/jsonjava/CookieIntegrationTest.java new file mode 100644 index 0000000000..c1a3505bbc --- /dev/null +++ b/json/src/test/java/com/baeldung/jsonjava/CookieIntegrationTest.java @@ -0,0 +1,29 @@ +package com.baeldung.jsonjava; + +import static org.junit.Assert.assertEquals; + +import org.json.Cookie; +import org.json.JSONObject; +import org.junit.Test; + +public class CookieIntegrationTest { + @Test + public void givenCookieString_thenConvertToJSONObject() { + String cookie = "username=John Doe; expires=Thu, 18 Dec 2013 12:00:00 UTC; path=/"; + JSONObject cookieJO = Cookie.toJSONObject(cookie); + + assertEquals("{\"path\":\"/\",\"expires\":\"Thu, 18 Dec 2013 12:00:00 UTC\",\"name\":\"username\",\"value\":\"John Doe\"}", cookieJO.toString()); + } + + @Test + public void givenJSONObject_thenConvertToCookieString() { + JSONObject cookieJO = new JSONObject(); + cookieJO.put("name", "username"); + cookieJO.put("value", "John Doe"); + cookieJO.put("expires", "Thu, 18 Dec 2013 12:00:00 UTC"); + cookieJO.put("path", "/"); + String cookie = Cookie.toString(cookieJO); + + assertEquals("username=John Doe;expires=Thu, 18 Dec 2013 12:00:00 UTC;path=/", cookie.toString()); + } +} diff --git a/json/src/test/java/com/baeldung/jsonjava/HTTPIntegrationTest.java b/json/src/test/java/com/baeldung/jsonjava/HTTPIntegrationTest.java new file mode 100644 index 0000000000..1aa0427c7e --- /dev/null +++ b/json/src/test/java/com/baeldung/jsonjava/HTTPIntegrationTest.java @@ -0,0 +1,25 @@ +package com.baeldung.jsonjava; + +import static org.junit.Assert.assertEquals; +import org.json.HTTP; +import org.json.JSONObject; +import org.junit.Test; + +public class HTTPIntegrationTest { + @Test + public void givenJSONObject_thenConvertToHTTPHeader() { + JSONObject jo = new JSONObject(); + jo.put("Method", "POST"); + jo.put("Request-URI", "http://www.example.com/"); + jo.put("HTTP-Version", "HTTP/1.1"); + + assertEquals("POST \"http://www.example.com/\" HTTP/1.1"+HTTP.CRLF+HTTP.CRLF, HTTP.toString(jo)); + } + + @Test + public void givenHTTPHeader_thenConvertToJSONObject() { + JSONObject obj = HTTP.toJSONObject("POST \"http://www.example.com/\" HTTP/1.1"); + + assertEquals("{\"Request-URI\":\"http://www.example.com/\",\"Method\":\"POST\",\"HTTP-Version\":\"HTTP/1.1\"}", obj.toString()); + } +} diff --git a/json/src/test/java/com/baeldung/jsonjava/JSONArrayIntegrationTest.java b/json/src/test/java/com/baeldung/jsonjava/JSONArrayIntegrationTest.java new file mode 100644 index 0000000000..c956232abe --- /dev/null +++ b/json/src/test/java/com/baeldung/jsonjava/JSONArrayIntegrationTest.java @@ -0,0 +1,47 @@ +package com.baeldung.jsonjava; + +import static org.junit.Assert.assertEquals; + +import java.util.ArrayList; +import java.util.List; + +import org.json.JSONArray; +import org.json.JSONObject; +import org.junit.Test; + +public class JSONArrayIntegrationTest { + @Test + public void givenJSONJava_thenCreateNewJSONArrayFromScratch() { + JSONArray ja = new JSONArray(); + ja.put(Boolean.TRUE); + ja.put("lorem ipsum"); + + // We can also put a JSONObject in JSONArray + JSONObject jo = new JSONObject(); + jo.put("name", "jon doe"); + jo.put("age", "22"); + jo.put("city", "chicago"); + + ja.put(jo); + + assertEquals("[true,\"lorem ipsum\",{\"city\":\"chicago\",\"name\":\"jon doe\",\"age\":\"22\"}]", ja.toString()); + } + + @Test + public void givenJsonString_thenCreateNewJSONArray() { + JSONArray ja = new JSONArray("[true, \"lorem ipsum\", 215]"); + assertEquals("[true,\"lorem ipsum\",215]", ja.toString()); + } + + @Test + public void givenListObject_thenConvertItToJSONArray() { + List list = new ArrayList<>(); + list.add("California"); + list.add("Texas"); + list.add("Hawaii"); + list.add("Alaska"); + + JSONArray ja = new JSONArray(list); + assertEquals("[\"California\",\"Texas\",\"Hawaii\",\"Alaska\"]", ja.toString()); + } +} \ No newline at end of file diff --git a/json/src/test/java/com/baeldung/jsonjava/JSONObjectIntegrationTest.java b/json/src/test/java/com/baeldung/jsonjava/JSONObjectIntegrationTest.java new file mode 100644 index 0000000000..70f7921797 --- /dev/null +++ b/json/src/test/java/com/baeldung/jsonjava/JSONObjectIntegrationTest.java @@ -0,0 +1,53 @@ +package com.baeldung.jsonjava; + +import static org.junit.Assert.assertEquals; + +import java.util.HashMap; +import java.util.Map; + +import org.json.JSONObject; +import org.junit.Test; + +public class JSONObjectIntegrationTest { + @Test + public void givenJSONJava_thenCreateNewJSONObject() { + JSONObject jo = new JSONObject(); + jo.put("name", "jon doe"); + jo.put("age", "22"); + jo.put("city", "chicago"); + + assertEquals("{\"city\":\"chicago\",\"name\":\"jon doe\",\"age\":\"22\"}", jo.toString()); + + } + + @Test + public void givenMapObject_thenCreateJSONObject() { + Map map = new HashMap<>(); + map.put("name", "jon doe"); + map.put("age", "22"); + map.put("city", "chicago"); + JSONObject jo = new JSONObject(map); + + assertEquals("{\"name\":\"jon doe\",\"city\":\"chicago\",\"age\":\"22\"}", jo.toString()); + } + + @Test + public void givenJsonString_thenCreateJSONObject() { + JSONObject jo = new JSONObject( + "{\"city\":\"chicago\",\"name\":\"jon doe\",\"age\":\"22\"}" + ); + + assertEquals("{\"city\":\"chicago\",\"name\":\"jon doe\",\"age\":\"22\"}", jo.toString()); + } + + @Test + public void givenDemoBean_thenCreateJSONObject() { + DemoBean demo = new DemoBean(); + demo.setId(1); + demo.setName("lorem ipsum"); + demo.setActive(true); + + JSONObject jo = new JSONObject(demo); + assertEquals("{\"name\":\"lorem ipsum\",\"active\":true,\"id\":1}", jo.toString()); + } +} diff --git a/json/src/test/java/com/baeldung/jsonjava/JSONTokenerIntegrationTest.java b/json/src/test/java/com/baeldung/jsonjava/JSONTokenerIntegrationTest.java new file mode 100644 index 0000000000..4fe8f27231 --- /dev/null +++ b/json/src/test/java/com/baeldung/jsonjava/JSONTokenerIntegrationTest.java @@ -0,0 +1,21 @@ +package com.baeldung.jsonjava; + +import static org.junit.Assert.assertEquals; + +import org.json.JSONTokener; +import org.junit.Test; + +public class JSONTokenerIntegrationTest { + @Test + public void givenString_convertItToJSONTokens() { + String str = "Sample String"; + JSONTokener jt = new JSONTokener(str); + + char[] expectedTokens = str.toCharArray(); + int index = 0; + + while(jt.more()) { + assertEquals(expectedTokens[index++], jt.next()); + } + } +} From 72c9fea7e23c479468464b9ff7e4470d11aaf6eb Mon Sep 17 00:00:00 2001 From: tamasradu Date: Thu, 1 Feb 2018 15:56:36 +0200 Subject: [PATCH 19/28] Radutamas/bael 1487 (#3569) * Code for test article: Different Types of Bean Injection in Spring * Adding jUnits for test article: Different Types of Bean Injection in Spring * BAEL-1265: Adding jUnit for article * BAEL-1265: Closing ExecutorService in jUnit * BAEL-1487: Adding test for AsyncHtpClient tutorial --- libraries/pom.xml | 9 +- .../AsyncHttpClientTestCase.java | 219 ++++++++++++++++++ 2 files changed, 227 insertions(+), 1 deletion(-) create mode 100644 libraries/src/test/java/com/baeldung/asynchttpclient/AsyncHttpClientTestCase.java diff --git a/libraries/pom.xml b/libraries/pom.xml index a330494bb3..e8f7c470a3 100644 --- a/libraries/pom.xml +++ b/libraries/pom.xml @@ -116,6 +116,12 @@ + + + org.asynchttpclient + async-http-client + ${async.http.client.version} + org.beykery @@ -766,7 +772,7 @@ 1.1.3-rc.5 1.4.0 1.1.0 - 4.1.15.Final + 4.1.20.Final 4.1 4.12 0.10 @@ -796,5 +802,6 @@ 1.0.0 1.7.0 3.0.14 + 2.2.0 \ No newline at end of file diff --git a/libraries/src/test/java/com/baeldung/asynchttpclient/AsyncHttpClientTestCase.java b/libraries/src/test/java/com/baeldung/asynchttpclient/AsyncHttpClientTestCase.java new file mode 100644 index 0000000000..7f9c2699fe --- /dev/null +++ b/libraries/src/test/java/com/baeldung/asynchttpclient/AsyncHttpClientTestCase.java @@ -0,0 +1,219 @@ +package com.baeldung.asynchttpclient; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; + +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import org.asynchttpclient.AsyncCompletionHandler; +import org.asynchttpclient.AsyncHandler; +import org.asynchttpclient.AsyncHttpClient; +import org.asynchttpclient.AsyncHttpClientConfig; +import org.asynchttpclient.BoundRequestBuilder; +import org.asynchttpclient.Dsl; +import org.asynchttpclient.HttpResponseBodyPart; +import org.asynchttpclient.HttpResponseStatus; +import org.asynchttpclient.ListenableFuture; +import org.asynchttpclient.Request; +import org.asynchttpclient.Response; +import org.asynchttpclient.ws.WebSocket; +import org.asynchttpclient.ws.WebSocketListener; +import org.asynchttpclient.ws.WebSocketUpgradeHandler; +import org.junit.Before; +import org.junit.Test; + +import io.netty.handler.codec.http.HttpHeaders; + +public class AsyncHttpClientTestCase { + + private static AsyncHttpClient HTTP_CLIENT; + + @Before + public void setup() { + + AsyncHttpClientConfig clientConfig = Dsl.config().setConnectTimeout(15000).setRequestTimeout(15000).build(); + HTTP_CLIENT = Dsl.asyncHttpClient(clientConfig); + } + + @Test + public void givenHttpClient_executeSyncGetRequest() { + + BoundRequestBuilder boundGetRequest = HTTP_CLIENT.prepareGet("http://www.baeldung.com"); + + Future responseFuture = boundGetRequest.execute(); + try { + Response response = responseFuture.get(5000, TimeUnit.MILLISECONDS); + assertNotNull(response); + assertEquals(200, response.getStatusCode()); + + } catch (InterruptedException e) { + e.printStackTrace(); + } catch (ExecutionException e) { + e.printStackTrace(); + } catch (TimeoutException e) { + e.printStackTrace(); + } + + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + @Test + public void givenHttpClient_executeAsyncGetRequest() { + + // execute an unbound GET request + Request unboundGetRequest = Dsl.get("http://www.baeldung.com").build(); + + HTTP_CLIENT.executeRequest(unboundGetRequest, new AsyncCompletionHandler() { + @Override + public Integer onCompleted(Response response) throws Exception { + + int resposeStatusCode = response.getStatusCode(); + assertEquals(200, resposeStatusCode); + return resposeStatusCode; + } + }); + + // execute a bound GET request + BoundRequestBuilder boundGetRequest = HTTP_CLIENT.prepareGet("http://www.baeldung.com"); + + boundGetRequest.execute(new AsyncCompletionHandler() { + @Override + public Integer onCompleted(Response response) throws Exception { + + int resposeStatusCode = response.getStatusCode(); + assertEquals(200, resposeStatusCode); + return resposeStatusCode; + } + }); + + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + @Test + public void givenHttpClient_executeAsyncGetRequestWithAsyncHandler() { + + // execute an unbound GET request + Request unboundGetRequest = Dsl.get("http://www.baeldung.com").build(); + + HTTP_CLIENT.executeRequest(unboundGetRequest, new AsyncHandler() { + + int responseStatusCode = -1; + + @Override + public State onStatusReceived(HttpResponseStatus responseStatus) throws Exception { + responseStatusCode = responseStatus.getStatusCode(); + return State.CONTINUE; + } + + @Override + public State onHeadersReceived(HttpHeaders headers) throws Exception { + return State.CONTINUE; + } + + @Override + public State onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception { + return State.CONTINUE; + } + + @Override + public void onThrowable(Throwable t) { + + } + + @Override + public Integer onCompleted() throws Exception { + assertEquals(200, responseStatusCode); + return responseStatusCode; + } + }); + + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + @Test + public void givenHttpClient_executeAsyncGetRequestWithListanableFuture() { + // execute an unbound GET request + Request unboundGetRequest = Dsl.get("http://www.baeldung.com").build(); + + ListenableFuture listenableFuture = HTTP_CLIENT.executeRequest(unboundGetRequest); + listenableFuture.addListener(() -> { + Response response; + try { + response = listenableFuture.get(5000, TimeUnit.MILLISECONDS); + assertEquals(200, response.getStatusCode()); + } catch (InterruptedException | ExecutionException | TimeoutException e) { + e.printStackTrace(); + } + + }, Executors.newCachedThreadPool()); + + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + @Test + public void givenWebSocketClient_tryToConnect() { + + WebSocketUpgradeHandler.Builder upgradeHandlerBuilder = new WebSocketUpgradeHandler.Builder(); + WebSocketUpgradeHandler wsHandler = upgradeHandlerBuilder.addWebSocketListener(new WebSocketListener() { + @Override + public void onOpen(WebSocket websocket) { + // WebSocket connection opened + } + + @Override + public void onClose(WebSocket websocket, int code, String reason) { + // WebSocket connection closed + } + + @Override + public void onError(Throwable t) { + // WebSocket connection error + assertTrue(t.getMessage().contains("Request timeout")); + } + }).build(); + + WebSocket WEBSOCKET_CLIENT = null; + try { + WEBSOCKET_CLIENT = Dsl.asyncHttpClient() + .prepareGet("ws://localhost:5590/websocket") + .addHeader("header_name", "header_value") + .addQueryParam("key", "value") + .setRequestTimeout(5000) + .execute(wsHandler).get(); + + if (WEBSOCKET_CLIENT.isOpen()) { + WEBSOCKET_CLIENT.sendPingFrame(); + WEBSOCKET_CLIENT.sendTextFrame("test message"); + WEBSOCKET_CLIENT.sendBinaryFrame(new byte[] { 't', 'e', 's', 't' }); + } + + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } finally { + if (WEBSOCKET_CLIENT != null && WEBSOCKET_CLIENT.isOpen()) { + WEBSOCKET_CLIENT.sendCloseFrame(200, "OK"); + } + } + } +} From 310e31e2bd5c1ca5a4f021268f09e6b0808807e5 Mon Sep 17 00:00:00 2001 From: Alessio Stalla Date: Thu, 1 Feb 2018 20:30:54 +0100 Subject: [PATCH 20/28] Code for BAEL-68 (#3559) --- .../HibernateBootstrapIntegrationTest.java | 147 ++++++++++++++++++ 1 file changed, 147 insertions(+) diff --git a/persistence-modules/spring-hibernate-5/src/test/java/com/baeldung/hibernate/bootstrap/HibernateBootstrapIntegrationTest.java b/persistence-modules/spring-hibernate-5/src/test/java/com/baeldung/hibernate/bootstrap/HibernateBootstrapIntegrationTest.java index ffe82b7ced..c41423643a 100644 --- a/persistence-modules/spring-hibernate-5/src/test/java/com/baeldung/hibernate/bootstrap/HibernateBootstrapIntegrationTest.java +++ b/persistence-modules/spring-hibernate-5/src/test/java/com/baeldung/hibernate/bootstrap/HibernateBootstrapIntegrationTest.java @@ -8,11 +8,16 @@ import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.test.annotation.Commit; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.support.AnnotationConfigContextLoader; +import org.springframework.test.context.transaction.TestTransaction; import org.springframework.transaction.annotation.Transactional; +import static junit.framework.TestCase.assertFalse; +import static junit.framework.TestCase.assertTrue; + @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(classes = { HibernateConf.class }) @Transactional @@ -35,4 +40,146 @@ public class HibernateBootstrapIntegrationTest { Assert.assertNotNull(searchEntity); } + @Test + public void whenProgrammaticTransactionCommit_thenEntityIsInDatabase() { + assertTrue(TestTransaction.isActive()); + + //Save an entity and commit. + Session session = sessionFactory.getCurrentSession(); + + TestEntity newEntity = new TestEntity(); + newEntity.setId(1); + session.save(newEntity); + + TestEntity searchEntity = session.find(TestEntity.class, 1); + + Assert.assertNotNull(searchEntity); + assertTrue(TestTransaction.isFlaggedForRollback()); + + TestTransaction.flagForCommit(); + TestTransaction.end(); + + assertFalse(TestTransaction.isFlaggedForRollback()); + assertFalse(TestTransaction.isActive()); + + //Check that the entity is still there in a new transaction, + //then delete it, but don't commit. + TestTransaction.start(); + + assertTrue(TestTransaction.isFlaggedForRollback()); + assertTrue(TestTransaction.isActive()); + + session = sessionFactory.getCurrentSession(); + searchEntity = session.find(TestEntity.class, 1); + + Assert.assertNotNull(searchEntity); + + session.delete(searchEntity); + session.flush(); + + TestTransaction.end(); + + assertFalse(TestTransaction.isActive()); + + //Check that the entity is still there in a new transaction, + //then delete it and commit. + TestTransaction.start(); + + session = sessionFactory.getCurrentSession(); + searchEntity = session.find(TestEntity.class, 1); + + Assert.assertNotNull(searchEntity); + + session.delete(searchEntity); + session.flush(); + + assertTrue(TestTransaction.isActive()); + + TestTransaction.flagForCommit(); + TestTransaction.end(); + + assertFalse(TestTransaction.isActive()); + + //Check that the entity is no longer there in a new transaction. + TestTransaction.start(); + + assertTrue(TestTransaction.isActive()); + + session = sessionFactory.getCurrentSession(); + searchEntity = session.find(TestEntity.class, 1); + + Assert.assertNull(searchEntity); + } + + @Test + @Commit + public void givenTransactionCommitDefault_whenProgrammaticTransactionCommit_thenEntityIsInDatabase() { + assertTrue(TestTransaction.isActive()); + + //Save an entity and commit. + Session session = sessionFactory.getCurrentSession(); + + TestEntity newEntity = new TestEntity(); + newEntity.setId(1); + session.save(newEntity); + + TestEntity searchEntity = session.find(TestEntity.class, 1); + + Assert.assertNotNull(searchEntity); + assertFalse(TestTransaction.isFlaggedForRollback()); + + TestTransaction.end(); + + assertFalse(TestTransaction.isFlaggedForRollback()); + assertFalse(TestTransaction.isActive()); + + //Check that the entity is still there in a new transaction, + //then delete it, but don't commit. + TestTransaction.start(); + + assertFalse(TestTransaction.isFlaggedForRollback()); + assertTrue(TestTransaction.isActive()); + + session = sessionFactory.getCurrentSession(); + searchEntity = session.find(TestEntity.class, 1); + + Assert.assertNotNull(searchEntity); + + session.delete(searchEntity); + session.flush(); + + TestTransaction.flagForRollback(); + TestTransaction.end(); + + assertFalse(TestTransaction.isActive()); + + //Check that the entity is still there in a new transaction, + //then delete it and commit. + TestTransaction.start(); + + session = sessionFactory.getCurrentSession(); + searchEntity = session.find(TestEntity.class, 1); + + Assert.assertNotNull(searchEntity); + + session.delete(searchEntity); + session.flush(); + + assertTrue(TestTransaction.isActive()); + + TestTransaction.end(); + + assertFalse(TestTransaction.isActive()); + + //Check that the entity is no longer there in a new transaction. + TestTransaction.start(); + + assertTrue(TestTransaction.isActive()); + + session = sessionFactory.getCurrentSession(); + searchEntity = session.find(TestEntity.class, 1); + + Assert.assertNull(searchEntity); + } + } From 55660e770254f96e274c98801a0ad9a60e0489f0 Mon Sep 17 00:00:00 2001 From: myluckagain Date: Fri, 2 Feb 2018 03:17:53 +0500 Subject: [PATCH 21/28] BAEL-1497 (#3568) --- .../designpatterns/observer/Channel.java | 5 ++ .../designpatterns/observer/NewsAgency.java | 24 ++++++++++ .../designpatterns/observer/NewsChannel.java | 20 ++++++++ .../designpatterns/observer/ONewsAgency.java | 13 +++++ .../designpatterns/observer/ONewsChannel.java | 22 +++++++++ .../observer/PCLNewsAgency.java | 28 +++++++++++ .../observer/PCLNewsChannel.java | 21 +++++++++ .../observer/ObserverIntegrationTest.java | 47 +++++++++++++++++++ 8 files changed, 180 insertions(+) create mode 100644 core-java/src/main/java/com/baeldung/designpatterns/observer/Channel.java create mode 100644 core-java/src/main/java/com/baeldung/designpatterns/observer/NewsAgency.java create mode 100644 core-java/src/main/java/com/baeldung/designpatterns/observer/NewsChannel.java create mode 100644 core-java/src/main/java/com/baeldung/designpatterns/observer/ONewsAgency.java create mode 100644 core-java/src/main/java/com/baeldung/designpatterns/observer/ONewsChannel.java create mode 100644 core-java/src/main/java/com/baeldung/designpatterns/observer/PCLNewsAgency.java create mode 100644 core-java/src/main/java/com/baeldung/designpatterns/observer/PCLNewsChannel.java create mode 100644 core-java/src/test/java/com/baeldung/designpatterns/observer/ObserverIntegrationTest.java diff --git a/core-java/src/main/java/com/baeldung/designpatterns/observer/Channel.java b/core-java/src/main/java/com/baeldung/designpatterns/observer/Channel.java new file mode 100644 index 0000000000..9ca2edac38 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/designpatterns/observer/Channel.java @@ -0,0 +1,5 @@ +package com.baeldung.designpatterns.observer; + +public interface Channel { + public void update(Object o); +} diff --git a/core-java/src/main/java/com/baeldung/designpatterns/observer/NewsAgency.java b/core-java/src/main/java/com/baeldung/designpatterns/observer/NewsAgency.java new file mode 100644 index 0000000000..0330fbdcdc --- /dev/null +++ b/core-java/src/main/java/com/baeldung/designpatterns/observer/NewsAgency.java @@ -0,0 +1,24 @@ +package com.baeldung.designpatterns.observer; + +import java.util.ArrayList; +import java.util.List; + +public class NewsAgency { + private String news; + private List channels = new ArrayList<>(); + + public void addObserver(Channel channel) { + this.channels.add(channel); + } + + public void removeObserver(Channel channel) { + this.channels.remove(channel); + } + + public void setNews(String news) { + this.news = news; + for (Channel channel : this.channels) { + channel.update(this.news); + } + } +} diff --git a/core-java/src/main/java/com/baeldung/designpatterns/observer/NewsChannel.java b/core-java/src/main/java/com/baeldung/designpatterns/observer/NewsChannel.java new file mode 100644 index 0000000000..09c22e0ad8 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/designpatterns/observer/NewsChannel.java @@ -0,0 +1,20 @@ +package com.baeldung.designpatterns.observer; + +public class NewsChannel implements Channel { + + private String news; + + @Override + public void update(Object news) { + this.setNews((String) news); + } + + public String getNews() { + return news; + } + + public void setNews(String news) { + this.news = news; + } + +} diff --git a/core-java/src/main/java/com/baeldung/designpatterns/observer/ONewsAgency.java b/core-java/src/main/java/com/baeldung/designpatterns/observer/ONewsAgency.java new file mode 100644 index 0000000000..2849820663 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/designpatterns/observer/ONewsAgency.java @@ -0,0 +1,13 @@ +package com.baeldung.designpatterns.observer; + +import java.util.Observable; + +public class ONewsAgency extends Observable { + private String news; + + public void setNews(String news) { + this.news = news; + setChanged(); + notifyObservers(news); + } +} diff --git a/core-java/src/main/java/com/baeldung/designpatterns/observer/ONewsChannel.java b/core-java/src/main/java/com/baeldung/designpatterns/observer/ONewsChannel.java new file mode 100644 index 0000000000..3989fe0286 --- /dev/null +++ b/core-java/src/main/java/com/baeldung/designpatterns/observer/ONewsChannel.java @@ -0,0 +1,22 @@ +package com.baeldung.designpatterns.observer; + +import java.util.Observable; +import java.util.Observer; + +public class ONewsChannel implements Observer { + + private String news; + + @Override + public void update(Observable o, Object news) { + this.setNews((String) news); + } + + public String getNews() { + return news; + } + + public void setNews(String news) { + this.news = news; + } +} diff --git a/core-java/src/main/java/com/baeldung/designpatterns/observer/PCLNewsAgency.java b/core-java/src/main/java/com/baeldung/designpatterns/observer/PCLNewsAgency.java new file mode 100644 index 0000000000..b05b97ab0b --- /dev/null +++ b/core-java/src/main/java/com/baeldung/designpatterns/observer/PCLNewsAgency.java @@ -0,0 +1,28 @@ +package com.baeldung.designpatterns.observer; + +import java.beans.PropertyChangeListener; +import java.beans.PropertyChangeSupport; + +public class PCLNewsAgency { + private String news; + + private PropertyChangeSupport support; + + public PCLNewsAgency() { + support = new PropertyChangeSupport(this); + } + + public void addPropertyChangeListener(PropertyChangeListener pcl) { + support.addPropertyChangeListener(pcl); + } + + public void removePropertyChangeListener(PropertyChangeListener pcl) { + support.removePropertyChangeListener(pcl); + } + + public void setNews(String value) { + support.firePropertyChange("news", this.news, value); + this.news = value; + + } +} diff --git a/core-java/src/main/java/com/baeldung/designpatterns/observer/PCLNewsChannel.java b/core-java/src/main/java/com/baeldung/designpatterns/observer/PCLNewsChannel.java new file mode 100644 index 0000000000..ff8d35463c --- /dev/null +++ b/core-java/src/main/java/com/baeldung/designpatterns/observer/PCLNewsChannel.java @@ -0,0 +1,21 @@ +package com.baeldung.designpatterns.observer; + +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +public class PCLNewsChannel implements PropertyChangeListener { + + private String news; + + public void propertyChange(PropertyChangeEvent evt) { + this.setNews((String) evt.getNewValue()); + } + + public String getNews() { + return news; + } + + public void setNews(String news) { + this.news = news; + } +} diff --git a/core-java/src/test/java/com/baeldung/designpatterns/observer/ObserverIntegrationTest.java b/core-java/src/test/java/com/baeldung/designpatterns/observer/ObserverIntegrationTest.java new file mode 100644 index 0000000000..a8a0e29990 --- /dev/null +++ b/core-java/src/test/java/com/baeldung/designpatterns/observer/ObserverIntegrationTest.java @@ -0,0 +1,47 @@ +package com.baeldung.designpatterns.observer; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +import com.baeldung.designpatterns.observer.NewsAgency; +import com.baeldung.designpatterns.observer.NewsChannel; + +public class ObserverIntegrationTest { + + @Test + public void whenChangingNewsAgencyState_thenNewsChannelNotified() { + + NewsAgency observable = new NewsAgency(); + NewsChannel observer = new NewsChannel(); + + observable.addObserver(observer); + + observable.setNews("news"); + assertEquals(observer.getNews(), "news"); + } + + @Test + public void whenChangingONewsAgencyState_thenONewsChannelNotified() { + + ONewsAgency observable = new ONewsAgency(); + ONewsChannel observer = new ONewsChannel(); + + observable.addObserver(observer); + + observable.setNews("news"); + assertEquals(observer.getNews(), "news"); + } + + @Test + public void whenChangingPCLNewsAgencyState_thenONewsChannelNotified() { + + PCLNewsAgency observable = new PCLNewsAgency(); + PCLNewsChannel observer = new PCLNewsChannel(); + + observable.addPropertyChangeListener(observer); + + observable.setNews("news"); + assertEquals(observer.getNews(), "news"); + } +} From c057808c6e9b86a97e1fbf5be8af050ed82a8f60 Mon Sep 17 00:00:00 2001 From: Nam Thai Nguyen Date: Fri, 2 Feb 2018 11:59:17 +0700 Subject: [PATCH 22/28] Modifies error messages --- .../assertj/custom/AssertJCustomAssertionsUnitTest.java | 4 ++-- .../com/baeldung/testing/assertj/custom/PersonAssert.java | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/AssertJCustomAssertionsUnitTest.java b/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/AssertJCustomAssertionsUnitTest.java index f9b5bad039..4c09311bac 100644 --- a/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/AssertJCustomAssertionsUnitTest.java +++ b/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/AssertJCustomAssertionsUnitTest.java @@ -25,7 +25,7 @@ public class AssertJCustomAssertionsUnitTest { assertThat(person).isAdult(); fail(); } catch (AssertionError e) { - org.assertj.core.api.Assertions.assertThat(e).hasMessage("Expected adult but was juvenile"); + org.assertj.core.api.Assertions.assertThat(e).hasMessage("Expected person to be adult"); } } @@ -38,7 +38,7 @@ public class AssertJCustomAssertionsUnitTest { assertThat(person).hasNickname("John"); fail(); } catch (AssertionError e) { - org.assertj.core.api.Assertions.assertThat(e).hasMessage("Expected nickname John but did not have"); + org.assertj.core.api.Assertions.assertThat(e).hasMessage("Expected person to have nickname John"); } } } diff --git a/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/PersonAssert.java b/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/PersonAssert.java index 4c071660f3..d6cc585e96 100644 --- a/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/PersonAssert.java +++ b/testing-modules/testing/src/test/java/com/baeldung/testing/assertj/custom/PersonAssert.java @@ -15,7 +15,7 @@ public class PersonAssert extends AbstractAssert { public PersonAssert hasFullName(String fullName) { isNotNull(); if (!actual.getFullName().equals(fullName)) { - failWithMessage("Expected full name %s but was %s", fullName, actual.getFullName()); + failWithMessage("Expected person to have full name %s but was %s", fullName, actual.getFullName()); } return this; } @@ -23,7 +23,7 @@ public class PersonAssert extends AbstractAssert { public PersonAssert isAdult() { isNotNull(); if (actual.getAge() < 18) { - failWithMessage("Expected adult but was juvenile"); + failWithMessage("Expected person to be adult"); } return this; } @@ -31,7 +31,7 @@ public class PersonAssert extends AbstractAssert { public PersonAssert hasNickname(String nickName) { isNotNull(); if (!actual.getNicknames().contains(nickName)) { - failWithMessage("Expected nickname %s but did not have", nickName); + failWithMessage("Expected person to have nickname %s", nickName); } return this; } From 2169be43014347905e0ff6a35e25020953c3bfc8 Mon Sep 17 00:00:00 2001 From: Grzegorz Piwowarek Date: Fri, 2 Feb 2018 15:40:03 +0100 Subject: [PATCH 23/28] Async refactor (#3570) --- .../AsyncHttpClientTestCase.java | 318 +++++++++--------- 1 file changed, 154 insertions(+), 164 deletions(-) diff --git a/libraries/src/test/java/com/baeldung/asynchttpclient/AsyncHttpClientTestCase.java b/libraries/src/test/java/com/baeldung/asynchttpclient/AsyncHttpClientTestCase.java index 7f9c2699fe..1398c2ba41 100644 --- a/libraries/src/test/java/com/baeldung/asynchttpclient/AsyncHttpClientTestCase.java +++ b/libraries/src/test/java/com/baeldung/asynchttpclient/AsyncHttpClientTestCase.java @@ -1,15 +1,6 @@ package com.baeldung.asynchttpclient; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.assertTrue; - -import java.util.concurrent.ExecutionException; -import java.util.concurrent.Executors; -import java.util.concurrent.Future; -import java.util.concurrent.TimeUnit; -import java.util.concurrent.TimeoutException; - +import io.netty.handler.codec.http.HttpHeaders; import org.asynchttpclient.AsyncCompletionHandler; import org.asynchttpclient.AsyncHandler; import org.asynchttpclient.AsyncHttpClient; @@ -27,193 +18,192 @@ import org.asynchttpclient.ws.WebSocketUpgradeHandler; import org.junit.Before; import org.junit.Test; -import io.netty.handler.codec.http.HttpHeaders; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; +import java.util.concurrent.TimeUnit; +import java.util.concurrent.TimeoutException; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertTrue; public class AsyncHttpClientTestCase { - private static AsyncHttpClient HTTP_CLIENT; + private static AsyncHttpClient HTTP_CLIENT; - @Before - public void setup() { + @Before + public void setup() { + AsyncHttpClientConfig clientConfig = Dsl.config().setConnectTimeout(15000).setRequestTimeout(15000).build(); + HTTP_CLIENT = Dsl.asyncHttpClient(clientConfig); + } - AsyncHttpClientConfig clientConfig = Dsl.config().setConnectTimeout(15000).setRequestTimeout(15000).build(); - HTTP_CLIENT = Dsl.asyncHttpClient(clientConfig); - } - - @Test - public void givenHttpClient_executeSyncGetRequest() { + @Test + public void givenHttpClient_executeSyncGetRequest() { - BoundRequestBuilder boundGetRequest = HTTP_CLIENT.prepareGet("http://www.baeldung.com"); + BoundRequestBuilder boundGetRequest = HTTP_CLIENT.prepareGet("http://www.baeldung.com"); - Future responseFuture = boundGetRequest.execute(); - try { - Response response = responseFuture.get(5000, TimeUnit.MILLISECONDS); - assertNotNull(response); - assertEquals(200, response.getStatusCode()); + Future responseFuture = boundGetRequest.execute(); + try { + Response response = responseFuture.get(5000, TimeUnit.MILLISECONDS); + assertNotNull(response); + assertEquals(200, response.getStatusCode()); + } catch (InterruptedException | ExecutionException | TimeoutException e) { + e.printStackTrace(); + } - } catch (InterruptedException e) { - e.printStackTrace(); - } catch (ExecutionException e) { - e.printStackTrace(); - } catch (TimeoutException e) { - e.printStackTrace(); - } - - try { - Thread.sleep(5000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } - @Test - public void givenHttpClient_executeAsyncGetRequest() { + @Test + public void givenHttpClient_executeAsyncGetRequest() { - // execute an unbound GET request - Request unboundGetRequest = Dsl.get("http://www.baeldung.com").build(); + // execute an unbound GET request + Request unboundGetRequest = Dsl.get("http://www.baeldung.com").build(); - HTTP_CLIENT.executeRequest(unboundGetRequest, new AsyncCompletionHandler() { - @Override - public Integer onCompleted(Response response) throws Exception { + HTTP_CLIENT.executeRequest(unboundGetRequest, new AsyncCompletionHandler() { + @Override + public Integer onCompleted(Response response) { - int resposeStatusCode = response.getStatusCode(); - assertEquals(200, resposeStatusCode); - return resposeStatusCode; - } - }); + int resposeStatusCode = response.getStatusCode(); + assertEquals(200, resposeStatusCode); + return resposeStatusCode; + } + }); - // execute a bound GET request - BoundRequestBuilder boundGetRequest = HTTP_CLIENT.prepareGet("http://www.baeldung.com"); + // execute a bound GET request + BoundRequestBuilder boundGetRequest = HTTP_CLIENT.prepareGet("http://www.baeldung.com"); - boundGetRequest.execute(new AsyncCompletionHandler() { - @Override - public Integer onCompleted(Response response) throws Exception { + boundGetRequest.execute(new AsyncCompletionHandler() { + @Override + public Integer onCompleted(Response response) { + int resposeStatusCode = response.getStatusCode(); + assertEquals(200, resposeStatusCode); + return resposeStatusCode; + } + }); - int resposeStatusCode = response.getStatusCode(); - assertEquals(200, resposeStatusCode); - return resposeStatusCode; - } - }); + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } - try { - Thread.sleep(5000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } + @Test + public void givenHttpClient_executeAsyncGetRequestWithAsyncHandler() { - @Test - public void givenHttpClient_executeAsyncGetRequestWithAsyncHandler() { + // execute an unbound GET request + Request unboundGetRequest = Dsl.get("http://www.baeldung.com").build(); - // execute an unbound GET request - Request unboundGetRequest = Dsl.get("http://www.baeldung.com").build(); + HTTP_CLIENT.executeRequest(unboundGetRequest, new AsyncHandler() { - HTTP_CLIENT.executeRequest(unboundGetRequest, new AsyncHandler() { + int responseStatusCode = -1; - int responseStatusCode = -1; + @Override + public State onStatusReceived(HttpResponseStatus responseStatus) { + responseStatusCode = responseStatus.getStatusCode(); + return State.CONTINUE; + } - @Override - public State onStatusReceived(HttpResponseStatus responseStatus) throws Exception { - responseStatusCode = responseStatus.getStatusCode(); - return State.CONTINUE; - } + @Override + public State onHeadersReceived(HttpHeaders headers) { + return State.CONTINUE; + } - @Override - public State onHeadersReceived(HttpHeaders headers) throws Exception { - return State.CONTINUE; - } + @Override + public State onBodyPartReceived(HttpResponseBodyPart bodyPart) { + return State.CONTINUE; + } - @Override - public State onBodyPartReceived(HttpResponseBodyPart bodyPart) throws Exception { - return State.CONTINUE; - } + @Override + public void onThrowable(Throwable t) { - @Override - public void onThrowable(Throwable t) { + } - } + @Override + public Integer onCompleted() { + assertEquals(200, responseStatusCode); + return responseStatusCode; + } + }); - @Override - public Integer onCompleted() throws Exception { - assertEquals(200, responseStatusCode); - return responseStatusCode; - } - }); + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } - try { - Thread.sleep(5000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } + @Test + public void givenHttpClient_executeAsyncGetRequestWithListanableFuture() { + // execute an unbound GET request + Request unboundGetRequest = Dsl.get("http://www.baeldung.com").build(); - @Test - public void givenHttpClient_executeAsyncGetRequestWithListanableFuture() { - // execute an unbound GET request - Request unboundGetRequest = Dsl.get("http://www.baeldung.com").build(); + ListenableFuture listenableFuture = HTTP_CLIENT.executeRequest(unboundGetRequest); + listenableFuture.addListener(() -> { + Response response; + try { + response = listenableFuture.get(5000, TimeUnit.MILLISECONDS); + assertEquals(200, response.getStatusCode()); + } catch (InterruptedException | ExecutionException | TimeoutException e) { + e.printStackTrace(); + } + }, Executors.newCachedThreadPool()); - ListenableFuture listenableFuture = HTTP_CLIENT.executeRequest(unboundGetRequest); - listenableFuture.addListener(() -> { - Response response; - try { - response = listenableFuture.get(5000, TimeUnit.MILLISECONDS); - assertEquals(200, response.getStatusCode()); - } catch (InterruptedException | ExecutionException | TimeoutException e) { - e.printStackTrace(); - } + try { + Thread.sleep(5000); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } - }, Executors.newCachedThreadPool()); + @Test + public void givenWebSocketClient_tryToConnect() { - try { - Thread.sleep(5000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } + WebSocketUpgradeHandler.Builder upgradeHandlerBuilder = new WebSocketUpgradeHandler.Builder(); + WebSocketUpgradeHandler wsHandler = upgradeHandlerBuilder.addWebSocketListener(new WebSocketListener() { + @Override + public void onOpen(WebSocket websocket) { + // WebSocket connection opened + } - @Test - public void givenWebSocketClient_tryToConnect() { + @Override + public void onClose(WebSocket websocket, int code, String reason) { + // WebSocket connection closed + } - WebSocketUpgradeHandler.Builder upgradeHandlerBuilder = new WebSocketUpgradeHandler.Builder(); - WebSocketUpgradeHandler wsHandler = upgradeHandlerBuilder.addWebSocketListener(new WebSocketListener() { - @Override - public void onOpen(WebSocket websocket) { - // WebSocket connection opened - } + @Override + public void onError(Throwable t) { + // WebSocket connection error + assertTrue(t.getMessage().contains("Request timeout")); + } + }).build(); - @Override - public void onClose(WebSocket websocket, int code, String reason) { - // WebSocket connection closed - } + WebSocket WEBSOCKET_CLIENT = null; + try { + WEBSOCKET_CLIENT = Dsl.asyncHttpClient() + .prepareGet("ws://localhost:5590/websocket") + .addHeader("header_name", "header_value") + .addQueryParam("key", "value") + .setRequestTimeout(5000) + .execute(wsHandler).get(); - @Override - public void onError(Throwable t) { - // WebSocket connection error - assertTrue(t.getMessage().contains("Request timeout")); - } - }).build(); - - WebSocket WEBSOCKET_CLIENT = null; - try { - WEBSOCKET_CLIENT = Dsl.asyncHttpClient() - .prepareGet("ws://localhost:5590/websocket") - .addHeader("header_name", "header_value") - .addQueryParam("key", "value") - .setRequestTimeout(5000) - .execute(wsHandler).get(); - - if (WEBSOCKET_CLIENT.isOpen()) { - WEBSOCKET_CLIENT.sendPingFrame(); - WEBSOCKET_CLIENT.sendTextFrame("test message"); - WEBSOCKET_CLIENT.sendBinaryFrame(new byte[] { 't', 'e', 's', 't' }); - } - - } catch (InterruptedException | ExecutionException e) { - e.printStackTrace(); - } finally { - if (WEBSOCKET_CLIENT != null && WEBSOCKET_CLIENT.isOpen()) { - WEBSOCKET_CLIENT.sendCloseFrame(200, "OK"); - } - } - } + if (WEBSOCKET_CLIENT.isOpen()) { + WEBSOCKET_CLIENT.sendPingFrame(); + WEBSOCKET_CLIENT.sendTextFrame("test message"); + WEBSOCKET_CLIENT.sendBinaryFrame(new byte[]{'t', 'e', 's', 't'}); + } + } catch (InterruptedException | ExecutionException e) { + e.printStackTrace(); + } finally { + if (WEBSOCKET_CLIENT != null && WEBSOCKET_CLIENT.isOpen()) { + WEBSOCKET_CLIENT.sendCloseFrame(200, "OK"); + } + } + } } From fa906a2b59420fd29fca9fa93ae291771c84a8d4 Mon Sep 17 00:00:00 2001 From: Tom Hombergs Date: Fri, 2 Feb 2018 21:01:22 +0100 Subject: [PATCH 24/28] removed Car class --- .../baeldung/testing/assertj/custom/Car.java | 22 ------------------- 1 file changed, 22 deletions(-) delete mode 100644 testing-modules/testing/src/main/java/com/baeldung/testing/assertj/custom/Car.java diff --git a/testing-modules/testing/src/main/java/com/baeldung/testing/assertj/custom/Car.java b/testing-modules/testing/src/main/java/com/baeldung/testing/assertj/custom/Car.java deleted file mode 100644 index e52ffee8e5..0000000000 --- a/testing-modules/testing/src/main/java/com/baeldung/testing/assertj/custom/Car.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.baeldung.testing.assertj.custom; - -public class Car { - private String type; - private Person owner; - - public Car(String type) { - this.type = type; - } - - public String getType() { - return type; - } - - public Person getOwner() { - return owner; - } - - public void setOwner(Person owner) { - this.owner = owner; - } -} From ff76cbc1fe12379b6e28ff63fb4ae80daa8a678e Mon Sep 17 00:00:00 2001 From: Jose Carvajal Date: Sat, 3 Feb 2018 05:00:27 +0100 Subject: [PATCH 25/28] Bael 113 (#3484) * BAEL-399: A Guide to Multitenancy in Hibernate 5 * Removed unused properties in profile 2 * Changes after code review * BAEL-113 * Changes after code review * Added main method in spring boot application * Removed extra files --- pom.xml | 1 + spring-jinq/pom.xml | 83 +++++++++++++++++++ .../baeldung/spring/jinq/JinqApplication.java | 12 +++ .../config/JinqProviderConfiguration.java | 18 ++++ .../baeldung/spring/jinq/entities/Car.java | 58 +++++++++++++ .../spring/jinq/entities/Manufacturer.java | 42 ++++++++++ .../repositories/BaseJinqRepositoryImpl.java | 26 ++++++ .../jinq/repositories/CarRepository.java | 27 ++++++ .../jinq/repositories/CarRepositoryImpl.java | 72 ++++++++++++++++ .../src/main/resources/application.properties | 7 ++ .../CarRepositoryIntegrationTest.java | 42 ++++++++++ 11 files changed, 388 insertions(+) create mode 100644 spring-jinq/pom.xml create mode 100644 spring-jinq/src/main/java/com/baeldung/spring/jinq/JinqApplication.java create mode 100644 spring-jinq/src/main/java/com/baeldung/spring/jinq/config/JinqProviderConfiguration.java create mode 100644 spring-jinq/src/main/java/com/baeldung/spring/jinq/entities/Car.java create mode 100644 spring-jinq/src/main/java/com/baeldung/spring/jinq/entities/Manufacturer.java create mode 100644 spring-jinq/src/main/java/com/baeldung/spring/jinq/repositories/BaseJinqRepositoryImpl.java create mode 100644 spring-jinq/src/main/java/com/baeldung/spring/jinq/repositories/CarRepository.java create mode 100644 spring-jinq/src/main/java/com/baeldung/spring/jinq/repositories/CarRepositoryImpl.java create mode 100644 spring-jinq/src/main/resources/application.properties create mode 100644 spring-jinq/src/test/java/com/baeldung/spring/jinq/repositories/CarRepositoryIntegrationTest.java diff --git a/pom.xml b/pom.xml index 4a25459fcb..582ee6696e 100644 --- a/pom.xml +++ b/pom.xml @@ -246,6 +246,7 @@ spring-zuul spring-reactor spring-vertx + spring-jinq spring-rest-embedded-tomcat diff --git a/spring-jinq/pom.xml b/spring-jinq/pom.xml new file mode 100644 index 0000000000..a895ae8dd4 --- /dev/null +++ b/spring-jinq/pom.xml @@ -0,0 +1,83 @@ + + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + 4.0.0 + spring-jinq + 0.1-SNAPSHOT + + spring-jinq + + jar + + + UTF-8 + 1.8 + + 1.8.22 + + + + + + org.springframework.boot + spring-boot-dependencies + 1.5.9.RELEASE + pom + import + + + + + + + org.jinq + jinq-jpa + ${jinq.version} + + + + + com.h2database + h2 + + + + org.hibernate + hibernate-entitymanager + + + + + org.springframework + spring-orm + + + + + org.springframework.boot + spring-boot-starter-test + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + ${java.version} + ${java.version} + ${project.build.sourceEncoding} + false + + + + + + diff --git a/spring-jinq/src/main/java/com/baeldung/spring/jinq/JinqApplication.java b/spring-jinq/src/main/java/com/baeldung/spring/jinq/JinqApplication.java new file mode 100644 index 0000000000..d53b585d36 --- /dev/null +++ b/spring-jinq/src/main/java/com/baeldung/spring/jinq/JinqApplication.java @@ -0,0 +1,12 @@ +package com.baeldung.spring.jinq; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; + +@SpringBootApplication +public class JinqApplication { + + public static void main(String[] args) { + SpringApplication.run(JinqApplication.class, args); + } +} diff --git a/spring-jinq/src/main/java/com/baeldung/spring/jinq/config/JinqProviderConfiguration.java b/spring-jinq/src/main/java/com/baeldung/spring/jinq/config/JinqProviderConfiguration.java new file mode 100644 index 0000000000..6d921045b7 --- /dev/null +++ b/spring-jinq/src/main/java/com/baeldung/spring/jinq/config/JinqProviderConfiguration.java @@ -0,0 +1,18 @@ +package com.baeldung.spring.jinq.config; + +import javax.persistence.EntityManagerFactory; + +import org.jinq.jpa.JinqJPAStreamProvider; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +public class JinqProviderConfiguration { + + @Bean + @Autowired + JinqJPAStreamProvider jinqProvider(EntityManagerFactory emf) { + return new JinqJPAStreamProvider(emf); + } +} diff --git a/spring-jinq/src/main/java/com/baeldung/spring/jinq/entities/Car.java b/spring-jinq/src/main/java/com/baeldung/spring/jinq/entities/Car.java new file mode 100644 index 0000000000..263e6c7622 --- /dev/null +++ b/spring-jinq/src/main/java/com/baeldung/spring/jinq/entities/Car.java @@ -0,0 +1,58 @@ +package com.baeldung.spring.jinq.entities; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.JoinColumn; +import javax.persistence.OneToOne; + +@Entity(name = "CAR") +public class Car { + private String model; + private String description; + private int year; + private String engine; + private Manufacturer manufacturer; + + @Id + public String getModel() { + return model; + } + + public void setModel(String model) { + this.model = model; + } + + public String getDescription() { + return description; + } + + public void setDescription(String description) { + this.description = description; + } + + public int getYear() { + return year; + } + + public void setYear(int year) { + this.year = year; + } + + public String getEngine() { + return engine; + } + + public void setEngine(String engine) { + this.engine = engine; + } + + @OneToOne + @JoinColumn(name = "name") + public Manufacturer getManufacturer() { + return manufacturer; + } + + public void setManufacturer(Manufacturer manufacturer) { + this.manufacturer = manufacturer; + } +} diff --git a/spring-jinq/src/main/java/com/baeldung/spring/jinq/entities/Manufacturer.java b/spring-jinq/src/main/java/com/baeldung/spring/jinq/entities/Manufacturer.java new file mode 100644 index 0000000000..f6e5fd23de --- /dev/null +++ b/spring-jinq/src/main/java/com/baeldung/spring/jinq/entities/Manufacturer.java @@ -0,0 +1,42 @@ +package com.baeldung.spring.jinq.entities; + +import java.util.List; + +import javax.persistence.Entity; +import javax.persistence.Id; +import javax.persistence.OneToMany; + +@Entity(name = "MANUFACTURER") +public class Manufacturer { + + private String name; + private String city; + private List cars; + + @Id + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getCity() { + return city; + } + + public void setCity(String city) { + this.city = city; + } + + @OneToMany(mappedBy = "model") + public List getCars() { + return cars; + } + + public void setCars(List cars) { + this.cars = cars; + } + +} diff --git a/spring-jinq/src/main/java/com/baeldung/spring/jinq/repositories/BaseJinqRepositoryImpl.java b/spring-jinq/src/main/java/com/baeldung/spring/jinq/repositories/BaseJinqRepositoryImpl.java new file mode 100644 index 0000000000..42b81ecc59 --- /dev/null +++ b/spring-jinq/src/main/java/com/baeldung/spring/jinq/repositories/BaseJinqRepositoryImpl.java @@ -0,0 +1,26 @@ +package com.baeldung.spring.jinq.repositories; + +import javax.persistence.EntityManager; +import javax.persistence.PersistenceContext; + +import org.jinq.jpa.JPAJinqStream; +import org.jinq.jpa.JinqJPAStreamProvider; +import org.springframework.beans.factory.annotation.Autowired; + +public abstract class BaseJinqRepositoryImpl { + @Autowired + private JinqJPAStreamProvider jinqDataProvider; + + @PersistenceContext + private EntityManager entityManager; + + protected abstract Class entityType(); + + public JPAJinqStream stream() { + return streamOf(entityType()); + } + + protected JPAJinqStream streamOf(Class clazz) { + return jinqDataProvider.streamAll(entityManager, clazz); + } +} diff --git a/spring-jinq/src/main/java/com/baeldung/spring/jinq/repositories/CarRepository.java b/spring-jinq/src/main/java/com/baeldung/spring/jinq/repositories/CarRepository.java new file mode 100644 index 0000000000..56f6106e08 --- /dev/null +++ b/spring-jinq/src/main/java/com/baeldung/spring/jinq/repositories/CarRepository.java @@ -0,0 +1,27 @@ +package com.baeldung.spring.jinq.repositories; + +import java.util.List; +import java.util.Optional; + +import org.jinq.tuples.Pair; +import org.jinq.tuples.Tuple3; + +import com.baeldung.spring.jinq.entities.Car; +import com.baeldung.spring.jinq.entities.Manufacturer; + +public interface CarRepository { + + Optional findByModel(String model); + + List findByModelAndDescription(String model, String desc); + + List> findWithModelYearAndEngine(); + + Optional findManufacturerByModel(String model); + + List> findCarsPerManufacturer(); + + long countCarsByModel(String model); + + List findAll(int skip, int limit); +} diff --git a/spring-jinq/src/main/java/com/baeldung/spring/jinq/repositories/CarRepositoryImpl.java b/spring-jinq/src/main/java/com/baeldung/spring/jinq/repositories/CarRepositoryImpl.java new file mode 100644 index 0000000000..bf16c87461 --- /dev/null +++ b/spring-jinq/src/main/java/com/baeldung/spring/jinq/repositories/CarRepositoryImpl.java @@ -0,0 +1,72 @@ +package com.baeldung.spring.jinq.repositories; + +import java.util.List; +import java.util.Optional; + +import org.jinq.orm.stream.JinqStream; +import org.jinq.tuples.Pair; +import org.jinq.tuples.Tuple3; +import org.springframework.stereotype.Repository; + +import com.baeldung.spring.jinq.entities.Car; +import com.baeldung.spring.jinq.entities.Manufacturer; + +@Repository +public class CarRepositoryImpl extends BaseJinqRepositoryImpl implements CarRepository { + + @Override + public Optional findByModel(String model) { + return stream().where(c -> c.getModel() + .equals(model)) + .findFirst(); + } + + @Override + public List findByModelAndDescription(String model, String desc) { + return stream().where(c -> c.getModel() + .equals(model) + && c.getDescription() + .contains(desc)) + .toList(); + } + + @Override + public List> findWithModelYearAndEngine() { + return stream().select(c -> new Tuple3<>(c.getModel(), c.getYear(), c.getEngine())) + .toList(); + } + + @Override + public Optional findManufacturerByModel(String model) { + return stream().where(c -> c.getModel() + .equals(model)) + .select(c -> c.getManufacturer()) + .findFirst(); + } + + @Override + public List> findCarsPerManufacturer() { + return streamOf(Manufacturer.class).join(m -> JinqStream.from(m.getCars())) + .toList(); + } + + @Override + public long countCarsByModel(String model) { + return stream().where(c -> c.getModel() + .equals(model)) + .count(); + } + + @Override + public List findAll(int skip, int limit) { + return stream().skip(skip) + .limit(limit) + .toList(); + } + + @Override + protected Class entityType() { + return Car.class; + } + +} diff --git a/spring-jinq/src/main/resources/application.properties b/spring-jinq/src/main/resources/application.properties new file mode 100644 index 0000000000..dc73bed0c5 --- /dev/null +++ b/spring-jinq/src/main/resources/application.properties @@ -0,0 +1,7 @@ +spring.datasource.url=jdbc:h2:~/jinq +spring.datasource.username=sa +spring.datasource.password= + +spring.jpa.hibernate.ddl-auto=create-drop +spring.jpa.show-sql=true +spring.jpa.properties.hibernate.format_sql=true \ No newline at end of file diff --git a/spring-jinq/src/test/java/com/baeldung/spring/jinq/repositories/CarRepositoryIntegrationTest.java b/spring-jinq/src/test/java/com/baeldung/spring/jinq/repositories/CarRepositoryIntegrationTest.java new file mode 100644 index 0000000000..9cb126cbaa --- /dev/null +++ b/spring-jinq/src/test/java/com/baeldung/spring/jinq/repositories/CarRepositoryIntegrationTest.java @@ -0,0 +1,42 @@ +package com.baeldung.spring.jinq.repositories; + +import static org.assertj.core.api.Assertions.assertThat; + +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 com.baeldung.spring.jinq.JinqApplication; + +@ContextConfiguration(classes = JinqApplication.class) +@RunWith(SpringJUnit4ClassRunner.class) +public class CarRepositoryIntegrationTest { + + @Autowired + private CarRepository repository; + + @Test + public void givenACar_whenFilter_thenShouldBeFound() { + assertThat(repository.findByModel("model1") + .isPresent()).isFalse(); + } + + @Test + public void givenACar_whenMultipleFilters_thenShouldBeFound() { + assertThat(repository.findByModelAndDescription("model1", "desc") + .isEmpty()).isTrue(); + } + + @Test + public void whenUseASelectClause() { + assertThat(repository.findWithModelYearAndEngine() + .isEmpty()).isTrue(); + } + + @Test + public void whenUsingOneToOneRelationship() { + assertThat(repository.findManufacturerByModel("model1")).isNotNull(); + } +} From 710c25fb010068882767bccaaa8c73a70922adcd Mon Sep 17 00:00:00 2001 From: Grzegorz Piwowarek Date: Sat, 3 Feb 2018 12:37:28 +0100 Subject: [PATCH 26/28] Ocheja fix (#3572) * Define beans for handling different message types in a lean chat app * Add class based spring beans configuration * Define spring configuration in XML for constructor based bean injection * Refactor package structure to separate constructor based bean injection code set from setter based bean injection code set * Define configuration and classes specific to setter-based bean injection. * Implement tests for constructor-based and setter-based bean injections * develop codes for explaining type erasure * Write unit tests for type erasure examples * Remove evaluation article code * Modify type erasure examples and unit tests * Modify type erasure examples and unit tests * Add expected exception in TypeErasureUnitTest * Correct grammar in class name * Implement File Manager app to demonstrate Polymorphism. Develop unit tests for Polymorphism article code * Add examples for static polymorphism * Change sysout statments to slf4j log info statements * Add assertions and expected errors check on Test * Add assertions and expected errors check on Test * Correct compile time error of symbol not found * Removed commented out non-compiling test. * Replace string concatenations with String.format * Replace string concatenations with String.format * Remove verbose file info descriptor and replace with simpler one * Add example codes for Hibernate Interceptors article Write tests for session-scoped and sessionFactory-scoped interceptors * Implement serializable on customInterceptorImpl * Implement examples for spring data with spring security integration * Remove webapp example implementations; too extensive --- .../interceptors/CustomInterceptorImpl.java | 2 +- spring-data-spring-security/README.md | 14 +++ spring-data-spring-security/pom.xml | 67 ++++++++++++ .../src/main/java/com/baeldung/AppConfig.java | 64 +++++++++++ .../com/baeldung/SpringSecurityConfig.java | 89 ++++++++++++++++ .../data/repositories/TweetRepository.java | 14 +++ .../data/repositories/UserRepository.java | 27 +++++ .../java/com/baeldung/models/AppUser.java | 83 +++++++++++++++ .../main/java/com/baeldung/models/Tweet.java | 63 +++++++++++ .../baeldung/security/AppUserPrincipal.java | 67 ++++++++++++ .../AuthenticationSuccessHandlerImpl.java | 28 +++++ .../security/CustomUserDetailsService.java | 40 +++++++ .../com/baeldung/util/DummyContentUtil.java | 63 +++++++++++ .../src/main/resources/application.properties | 0 .../main/resources/persistence-h2.properties | 8 ++ .../SpringDataWithSecurityTest.java | 100 ++++++++++++++++++ 16 files changed, 728 insertions(+), 1 deletion(-) create mode 100644 spring-data-spring-security/README.md create mode 100644 spring-data-spring-security/pom.xml create mode 100644 spring-data-spring-security/src/main/java/com/baeldung/AppConfig.java create mode 100644 spring-data-spring-security/src/main/java/com/baeldung/SpringSecurityConfig.java create mode 100644 spring-data-spring-security/src/main/java/com/baeldung/data/repositories/TweetRepository.java create mode 100644 spring-data-spring-security/src/main/java/com/baeldung/data/repositories/UserRepository.java create mode 100644 spring-data-spring-security/src/main/java/com/baeldung/models/AppUser.java create mode 100644 spring-data-spring-security/src/main/java/com/baeldung/models/Tweet.java create mode 100644 spring-data-spring-security/src/main/java/com/baeldung/security/AppUserPrincipal.java create mode 100644 spring-data-spring-security/src/main/java/com/baeldung/security/AuthenticationSuccessHandlerImpl.java create mode 100644 spring-data-spring-security/src/main/java/com/baeldung/security/CustomUserDetailsService.java create mode 100644 spring-data-spring-security/src/main/java/com/baeldung/util/DummyContentUtil.java create mode 100644 spring-data-spring-security/src/main/resources/application.properties create mode 100644 spring-data-spring-security/src/main/resources/persistence-h2.properties create mode 100644 spring-data-spring-security/src/test/java/com/baeldung/relationships/SpringDataWithSecurityTest.java diff --git a/hibernate5/src/main/java/com/baeldung/hibernate/interceptors/CustomInterceptorImpl.java b/hibernate5/src/main/java/com/baeldung/hibernate/interceptors/CustomInterceptorImpl.java index a84a981f7f..6736b39b64 100644 --- a/hibernate5/src/main/java/com/baeldung/hibernate/interceptors/CustomInterceptorImpl.java +++ b/hibernate5/src/main/java/com/baeldung/hibernate/interceptors/CustomInterceptorImpl.java @@ -9,7 +9,7 @@ import org.hibernate.Interceptor; import org.hibernate.Transaction; import org.hibernate.type.Type; -public class CustomInterceptorImpl implements Interceptor { +public class CustomInterceptorImpl implements Interceptor, Serializable { @Override public boolean onLoad(Object entity, Serializable id, Object[] state, String[] propertyNames, Type[] types) throws CallbackException { diff --git a/spring-data-spring-security/README.md b/spring-data-spring-security/README.md new file mode 100644 index 0000000000..15b4b50870 --- /dev/null +++ b/spring-data-spring-security/README.md @@ -0,0 +1,14 @@ +# About this project +This project contains examples from the [Spring Data with Spring Security](http://www.baeldung.com/spring-data-with-spring-security) article from Baeldung. + +# Running the project +The application uses [Spring Boot](http://projects.spring.io/spring-boot/), so it is easy to run. You can start it any of a few ways: +* Run the `main` method from `SpringDataRestApplication` +* Use the Maven Spring Boot plugin: `mvn spring-boot:run` +* Package the application as a JAR and run it using `java -jar spring-data-spring-security.jar` + +# Viewing the running application +To view the running application, visit [http://localhost:8080](http://localhost:8080) in your browser + +###Relevant Articles: +- [Spring Data with Spring Security](http://www.baeldung.com/spring-data-with-spring-security) diff --git a/spring-data-spring-security/pom.xml b/spring-data-spring-security/pom.xml new file mode 100644 index 0000000000..d6b671ee57 --- /dev/null +++ b/spring-data-spring-security/pom.xml @@ -0,0 +1,67 @@ + + + 4.0.0 + + com.baeldung + spring-data-spring-security + 1.0 + jar + + intro-spring-data-spring-security + Spring Data with Spring Security + + + parent-boot-5 + com.baeldung + 0.0.1-SNAPSHOT + ../parent-boot-5 + + + + + org.springframework.boot + spring-boot-starter + + + org.springframework.boot + spring-boot-starter-web + + + org.springframework.boot + spring-boot-starter-data-jpa + + + org.springframework.security + spring-security-data + + + org.springframework.boot + spring-boot-starter-security + + + org.springframework.security + spring-security-test + test + + + org.apache.tomcat.embed + tomcat-embed-jasper + + + + com.h2database + h2 + + + javax.servlet + jstl + + + + + ${project.artifactId} + + + + diff --git a/spring-data-spring-security/src/main/java/com/baeldung/AppConfig.java b/spring-data-spring-security/src/main/java/com/baeldung/AppConfig.java new file mode 100644 index 0000000000..16bbe8b326 --- /dev/null +++ b/spring-data-spring-security/src/main/java/com/baeldung/AppConfig.java @@ -0,0 +1,64 @@ +package com.baeldung; + +import java.util.Properties; + +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Import; +import org.springframework.context.annotation.PropertySource; +import org.springframework.core.env.Environment; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.jdbc.datasource.DriverManagerDataSource; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; + +@SpringBootApplication +@PropertySource("classpath:persistence-h2.properties") +@EnableJpaRepositories(basePackages = { "com.baeldung.data.repositories" }) +@EnableWebMvc +@Import(SpringSecurityConfig.class) +public class AppConfig extends WebMvcConfigurerAdapter { + + @Autowired + private Environment env; + + @Bean + public DataSource dataSource() { + final DriverManagerDataSource dataSource = new DriverManagerDataSource(); + dataSource.setDriverClassName(env.getProperty("driverClassName")); + dataSource.setUrl(env.getProperty("url")); + dataSource.setUsername(env.getProperty("user")); + dataSource.setPassword(env.getProperty("password")); + return dataSource; + } + + @Bean + public LocalContainerEntityManagerFactoryBean entityManagerFactory() { + final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); + em.setDataSource(dataSource()); + em.setPackagesToScan(new String[] { "com.baeldung.models" }); + em.setJpaVendorAdapter(new HibernateJpaVendorAdapter()); + em.setJpaProperties(additionalProperties()); + return em; + } + + final Properties additionalProperties() { + final Properties hibernateProperties = new Properties(); + if (env.getProperty("hibernate.hbm2ddl.auto") != null) { + hibernateProperties.setProperty("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); + } + if (env.getProperty("hibernate.dialect") != null) { + hibernateProperties.setProperty("hibernate.dialect", env.getProperty("hibernate.dialect")); + } + if (env.getProperty("hibernate.show_sql") != null) { + hibernateProperties.setProperty("hibernate.show_sql", env.getProperty("hibernate.show_sql")); + } + return hibernateProperties; + } + +} diff --git a/spring-data-spring-security/src/main/java/com/baeldung/SpringSecurityConfig.java b/spring-data-spring-security/src/main/java/com/baeldung/SpringSecurityConfig.java new file mode 100644 index 0000000000..ee13678a24 --- /dev/null +++ b/spring-data-spring-security/src/main/java/com/baeldung/SpringSecurityConfig.java @@ -0,0 +1,89 @@ +package com.baeldung; + +import javax.annotation.PostConstruct; +import javax.sql.DataSource; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.security.authentication.dao.DaoAuthenticationProvider; +import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder; +import org.springframework.security.config.annotation.web.builders.HttpSecurity; +import org.springframework.security.config.annotation.web.builders.WebSecurity; +import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity; +import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; +import org.springframework.security.crypto.password.PasswordEncoder; +import org.springframework.security.data.repository.query.SecurityEvaluationContextExtension; +import org.springframework.web.context.WebApplicationContext; + +import com.baeldung.security.AuthenticationSuccessHandlerImpl; +import com.baeldung.security.CustomUserDetailsService; + +@Configuration +@EnableWebSecurity +@ComponentScan("com.baeldung.security") +public class SpringSecurityConfig extends WebSecurityConfigurerAdapter { + + @Autowired + private WebApplicationContext applicationContext; + private CustomUserDetailsService userDetailsService; + @Autowired + private AuthenticationSuccessHandlerImpl successHandler; + @Autowired + private DataSource dataSource; + + @PostConstruct + public void completeSetup() { + userDetailsService = applicationContext.getBean(CustomUserDetailsService.class); + } + + @Override + protected void configure(final AuthenticationManagerBuilder auth) throws Exception { + auth.userDetailsService(userDetailsService) + .passwordEncoder(encoder()) + .and() + .authenticationProvider(authenticationProvider()) + .jdbcAuthentication() + .dataSource(dataSource); + } + + @Override + public void configure(WebSecurity web) throws Exception { + web.ignoring() + .antMatchers("/resources/**"); + } + + @Override + protected void configure(final HttpSecurity http) throws Exception { + http.authorizeRequests() + .antMatchers("/login") + .permitAll() + .and() + .formLogin() + .permitAll() + .successHandler(successHandler) + .and() + .csrf() + .disable(); + } + + @Bean + public DaoAuthenticationProvider authenticationProvider() { + final DaoAuthenticationProvider authProvider = new DaoAuthenticationProvider(); + authProvider.setUserDetailsService(userDetailsService); + authProvider.setPasswordEncoder(encoder()); + return authProvider; + } + + @Bean + public PasswordEncoder encoder() { + return new BCryptPasswordEncoder(11); + } + + @Bean + public SecurityEvaluationContextExtension securityEvaluationContextExtension() { + return new SecurityEvaluationContextExtension(); + } +} diff --git a/spring-data-spring-security/src/main/java/com/baeldung/data/repositories/TweetRepository.java b/spring-data-spring-security/src/main/java/com/baeldung/data/repositories/TweetRepository.java new file mode 100644 index 0000000000..7d6446ed0d --- /dev/null +++ b/spring-data-spring-security/src/main/java/com/baeldung/data/repositories/TweetRepository.java @@ -0,0 +1,14 @@ +package com.baeldung.data.repositories; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.PagingAndSortingRepository; + +import com.baeldung.models.Tweet; + +public interface TweetRepository extends PagingAndSortingRepository { + + @Query("select twt from Tweet twt JOIN twt.likes as lk where lk = ?#{ principal?.username } or twt.owner = ?#{ principal?.username }") + Page getMyTweetsAndTheOnesILiked(Pageable pageable); +} diff --git a/spring-data-spring-security/src/main/java/com/baeldung/data/repositories/UserRepository.java b/spring-data-spring-security/src/main/java/com/baeldung/data/repositories/UserRepository.java new file mode 100644 index 0000000000..9f13c3197e --- /dev/null +++ b/spring-data-spring-security/src/main/java/com/baeldung/data/repositories/UserRepository.java @@ -0,0 +1,27 @@ +package com.baeldung.data.repositories; + +import java.util.Date; +import java.util.List; + +import org.springframework.data.domain.Page; +import org.springframework.data.domain.Pageable; +import org.springframework.data.jpa.repository.Modifying; +import org.springframework.data.jpa.repository.Query; +import org.springframework.data.repository.CrudRepository; +import org.springframework.data.repository.query.Param; +import org.springframework.stereotype.Repository; +import org.springframework.transaction.annotation.Transactional; + +import com.baeldung.models.AppUser; +import com.baeldung.models.Tweet; + +public interface UserRepository extends CrudRepository { + AppUser findByUsername(String username); + + List findByName(String name); + + @Query("UPDATE AppUser u SET u.lastLogin=:lastLogin WHERE u.username = ?#{ principal?.username }") + @Modifying + @Transactional + public void updateLastLogin(@Param("lastLogin") Date lastLogin); +} diff --git a/spring-data-spring-security/src/main/java/com/baeldung/models/AppUser.java b/spring-data-spring-security/src/main/java/com/baeldung/models/AppUser.java new file mode 100644 index 0000000000..e48233f90a --- /dev/null +++ b/spring-data-spring-security/src/main/java/com/baeldung/models/AppUser.java @@ -0,0 +1,83 @@ +package com.baeldung.models; + +import java.util.Date; + +import javax.persistence.Column; +import javax.persistence.Entity; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; +import javax.persistence.Table; + +@Entity +@Table(name = "users") +public class AppUser { + + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE) + private long id; + + private String name; + @Column(unique = true) + private String username; + private String password; + private boolean enabled = true; + private Date lastLogin; + + private AppUser() { + } + + public AppUser(String name, String email, String password) { + this.username = email; + this.name = name; + this.password = password; + } + + 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 getUsername() { + return username; + } + + public void setUsername(String username) { + this.username = username; + } + + public String getPassword() { + return password; + } + + public void setPassword(String password) { + this.password = password; + } + + public boolean isEnabled() { + return enabled; + } + + public void setEnabled(boolean enabled) { + this.enabled = enabled; + } + + public Date getLastLogin() { + return lastLogin; + } + + public void setLastLogin(Date lastLogin) { + this.lastLogin = lastLogin; + } +} diff --git a/spring-data-spring-security/src/main/java/com/baeldung/models/Tweet.java b/spring-data-spring-security/src/main/java/com/baeldung/models/Tweet.java new file mode 100644 index 0000000000..b2e45009f6 --- /dev/null +++ b/spring-data-spring-security/src/main/java/com/baeldung/models/Tweet.java @@ -0,0 +1,63 @@ +package com.baeldung.models; + +import java.util.HashSet; +import java.util.Set; + +import javax.persistence.ElementCollection; +import javax.persistence.Entity; +import javax.persistence.FetchType; +import javax.persistence.GeneratedValue; +import javax.persistence.GenerationType; +import javax.persistence.Id; + +@Entity +public class Tweet { + @Id + @GeneratedValue(strategy = GenerationType.SEQUENCE) + private long id; + private String tweet; + private String owner; + @ElementCollection(targetClass = String.class, fetch = FetchType.EAGER) + private Set likes = new HashSet(); + + public long getId() { + return id; + } + + public void setId(long id) { + this.id = id; + } + + private Tweet() { + } + + public Tweet(String tweet, String owner) { + this.tweet = tweet; + this.owner = owner; + } + + public String getTweet() { + return tweet; + } + + public void setTweet(String tweet) { + this.tweet = tweet; + } + + public String getOwner() { + return owner; + } + + public void setOwner(String owner) { + this.owner = owner; + } + + public Set getLikes() { + return likes; + } + + public void setLikes(Set likes) { + this.likes = likes; + } + +} diff --git a/spring-data-spring-security/src/main/java/com/baeldung/security/AppUserPrincipal.java b/spring-data-spring-security/src/main/java/com/baeldung/security/AppUserPrincipal.java new file mode 100644 index 0000000000..195f9f7bf6 --- /dev/null +++ b/spring-data-spring-security/src/main/java/com/baeldung/security/AppUserPrincipal.java @@ -0,0 +1,67 @@ +package com.baeldung.security; + +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.core.authority.SimpleGrantedAuthority; +import org.springframework.security.core.userdetails.UserDetails; + +import com.baeldung.models.AppUser; + +public class AppUserPrincipal implements UserDetails { + + private final AppUser user; + + // + + public AppUserPrincipal(AppUser user) { + this.user = user; + } + + // + + @Override + public String getUsername() { + return user.getUsername(); + } + + @Override + public String getPassword() { + return user.getPassword(); + } + + @Override + public Collection getAuthorities() { + final List authorities = Collections.singletonList(new SimpleGrantedAuthority("User")); + return authorities; + } + + @Override + public boolean isAccountNonExpired() { + return true; + } + + @Override + public boolean isAccountNonLocked() { + return true; + } + + @Override + public boolean isCredentialsNonExpired() { + return true; + } + + @Override + public boolean isEnabled() { + return true; + } + + // + + public AppUser getAppUser() { + return user; + } + +} diff --git a/spring-data-spring-security/src/main/java/com/baeldung/security/AuthenticationSuccessHandlerImpl.java b/spring-data-spring-security/src/main/java/com/baeldung/security/AuthenticationSuccessHandlerImpl.java new file mode 100644 index 0000000000..3fc2bc6559 --- /dev/null +++ b/spring-data-spring-security/src/main/java/com/baeldung/security/AuthenticationSuccessHandlerImpl.java @@ -0,0 +1,28 @@ +package com.baeldung.security; + +import java.io.IOException; +import java.util.Date; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.Authentication; +import org.springframework.security.web.authentication.AuthenticationSuccessHandler; +import org.springframework.stereotype.Component; + +import com.baeldung.data.repositories.UserRepository; + +@Component +public class AuthenticationSuccessHandlerImpl implements AuthenticationSuccessHandler { + + @Autowired + private UserRepository userRepository; + + @Override + public void onAuthenticationSuccess(HttpServletRequest arg0, HttpServletResponse arg1, Authentication arg2) throws IOException, ServletException { + userRepository.updateLastLogin(new Date()); + } + +} diff --git a/spring-data-spring-security/src/main/java/com/baeldung/security/CustomUserDetailsService.java b/spring-data-spring-security/src/main/java/com/baeldung/security/CustomUserDetailsService.java new file mode 100644 index 0000000000..016f4f7fa9 --- /dev/null +++ b/spring-data-spring-security/src/main/java/com/baeldung/security/CustomUserDetailsService.java @@ -0,0 +1,40 @@ +package com.baeldung.security; + +import javax.annotation.PostConstruct; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.security.core.userdetails.UserDetails; +import org.springframework.security.core.userdetails.UserDetailsService; +import org.springframework.security.core.userdetails.UsernameNotFoundException; +import org.springframework.stereotype.Service; +import org.springframework.web.context.WebApplicationContext; + +import com.baeldung.data.repositories.UserRepository; +import com.baeldung.models.AppUser; + +@Service +public class CustomUserDetailsService implements UserDetailsService { + + @Autowired + private WebApplicationContext applicationContext; + private UserRepository userRepository; + + public CustomUserDetailsService() { + super(); + } + + @PostConstruct + public void completeSetup() { + userRepository = applicationContext.getBean(UserRepository.class); + } + + @Override + public UserDetails loadUserByUsername(final String username) { + final AppUser appUser = userRepository.findByUsername(username); + if (appUser == null) { + throw new UsernameNotFoundException(username); + } + return new AppUserPrincipal(appUser); + } + +} diff --git a/spring-data-spring-security/src/main/java/com/baeldung/util/DummyContentUtil.java b/spring-data-spring-security/src/main/java/com/baeldung/util/DummyContentUtil.java new file mode 100644 index 0000000000..f1640264d2 --- /dev/null +++ b/spring-data-spring-security/src/main/java/com/baeldung/util/DummyContentUtil.java @@ -0,0 +1,63 @@ +package com.baeldung.util; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.Random; +import java.util.stream.Collectors; +import java.util.stream.IntStream; + +import org.springframework.security.core.GrantedAuthority; +import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder; + +import com.baeldung.models.AppUser; +import com.baeldung.models.Tweet; + +public class DummyContentUtil { + + public static final List generateDummyUsers() { + List appUsers = new ArrayList<>(); + BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder(); + appUsers.add(new AppUser("Lionel Messi", "lionel@messi.com", passwordEncoder.encode("li1234"))); + appUsers.add(new AppUser("Cristiano Ronaldo", "cristiano@ronaldo.com", passwordEncoder.encode("c1234"))); + appUsers.add(new AppUser("Neymar Dos Santos", "neymar@neymar.com", passwordEncoder.encode("n1234"))); + appUsers.add(new AppUser("Luiz Suarez", "luiz@suarez.com", passwordEncoder.encode("lu1234"))); + appUsers.add(new AppUser("Andres Iniesta", "andres@iniesta.com", passwordEncoder.encode("a1234"))); + appUsers.add(new AppUser("Ivan Rakitic", "ivan@rakitic.com", passwordEncoder.encode("i1234"))); + appUsers.add(new AppUser("Ousman Dembele", "ousman@dembele.com", passwordEncoder.encode("o1234"))); + appUsers.add(new AppUser("Sergio Busquet", "sergio@busquet.com", passwordEncoder.encode("s1234"))); + appUsers.add(new AppUser("Gerard Pique", "gerard@pique.com", passwordEncoder.encode("g1234"))); + appUsers.add(new AppUser("Ter Stergen", "ter@stergen.com", passwordEncoder.encode("t1234"))); + return appUsers; + } + + public static final List generateDummyTweets(List users) { + List tweets = new ArrayList<>(); + Random random = new Random(); + IntStream.range(0, 9) + .sequential() + .forEach(i -> { + Tweet twt = new Tweet(String.format("Tweet %d", i), users.get(random.nextInt(users.size())) + .getUsername()); + twt.getLikes() + .addAll(users.subList(0, random.nextInt(users.size())) + .stream() + .map(AppUser::getUsername) + .collect(Collectors.toSet())); + tweets.add(twt); + }); + return tweets; + } + + public static Collection getAuthorities() { + Collection grantedAuthorities = new ArrayList(); + GrantedAuthority grantedAuthority = new GrantedAuthority() { + public String getAuthority() { + return "ROLE_USER"; + } + }; + grantedAuthorities.add(grantedAuthority); + return grantedAuthorities; + } + +} diff --git a/spring-data-spring-security/src/main/resources/application.properties b/spring-data-spring-security/src/main/resources/application.properties new file mode 100644 index 0000000000..e69de29bb2 diff --git a/spring-data-spring-security/src/main/resources/persistence-h2.properties b/spring-data-spring-security/src/main/resources/persistence-h2.properties new file mode 100644 index 0000000000..a4b2af6361 --- /dev/null +++ b/spring-data-spring-security/src/main/resources/persistence-h2.properties @@ -0,0 +1,8 @@ +driverClassName=org.h2.Driver +url=jdbc:h2:mem:myDb;DB_CLOSE_DELAY=-1 +username=sa +password= + +hibernate.dialect=org.hibernate.dialect.H2Dialect +hibernate.show_sql=false +hibernate.hbm2ddl.auto=create-drop \ No newline at end of file diff --git a/spring-data-spring-security/src/test/java/com/baeldung/relationships/SpringDataWithSecurityTest.java b/spring-data-spring-security/src/test/java/com/baeldung/relationships/SpringDataWithSecurityTest.java new file mode 100644 index 0000000000..dbbfe7e85e --- /dev/null +++ b/spring-data-spring-security/src/test/java/com/baeldung/relationships/SpringDataWithSecurityTest.java @@ -0,0 +1,100 @@ +package com.baeldung.relationships; + +import static org.springframework.util.Assert.isTrue; + +import java.util.Date; +import java.util.List; + +import javax.servlet.ServletContext; + +import org.junit.AfterClass; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.dao.InvalidDataAccessApiUsageException; +import org.springframework.data.domain.Page; +import org.springframework.data.domain.PageRequest; +import org.springframework.security.authentication.UsernamePasswordAuthenticationToken; +import org.springframework.security.core.Authentication; +import org.springframework.security.core.context.SecurityContextHolder; +import org.springframework.test.annotation.DirtiesContext; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringRunner; +import org.springframework.test.context.web.WebAppConfiguration; +import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; + +import com.baeldung.AppConfig; +import com.baeldung.data.repositories.TweetRepository; +import com.baeldung.data.repositories.UserRepository; +import com.baeldung.models.AppUser; +import com.baeldung.models.Tweet; +import com.baeldung.security.AppUserPrincipal; +import com.baeldung.util.DummyContentUtil; + +@RunWith(SpringRunner.class) +@WebAppConfiguration +@ContextConfiguration +@DirtiesContext +public class SpringDataWithSecurityTest { + AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); + @Autowired + private ServletContext servletContext; + private static UserRepository userRepository; + private static TweetRepository tweetRepository; + + @Before + public void testInit() { + ctx.register(AppConfig.class); + ctx.setServletContext(servletContext); + ctx.refresh(); + userRepository = ctx.getBean(UserRepository.class); + tweetRepository = ctx.getBean(TweetRepository.class); + List appUsers = (List) userRepository.save(DummyContentUtil.generateDummyUsers()); + tweetRepository.save(DummyContentUtil.generateDummyTweets(appUsers)); + } + + @AfterClass + public static void tearDown() { + tweetRepository.deleteAll(); + userRepository.deleteAll(); + } + + @Test + public void givenAppUser_whenLoginSuccessful_shouldUpdateLastLogin() { + AppUser appUser = userRepository.findByUsername("lionel@messi.com"); + Authentication auth = new UsernamePasswordAuthenticationToken(new AppUserPrincipal(appUser), null, DummyContentUtil.getAuthorities()); + SecurityContextHolder.getContext() + .setAuthentication(auth); + userRepository.updateLastLogin(new Date()); + } + + @Test(expected = InvalidDataAccessApiUsageException.class) + public void givenNoAppUserInSecurityContext_whenUpdateLastLoginAttempted_shouldFail() { + userRepository.updateLastLogin(new Date()); + } + + @Test + public void givenAppUser_whenLoginSuccessful_shouldReadMyPagedTweets() { + AppUser appUser = userRepository.findByUsername("lionel@messi.com"); + Authentication auth = new UsernamePasswordAuthenticationToken(new AppUserPrincipal(appUser), null, DummyContentUtil.getAuthorities()); + SecurityContextHolder.getContext() + .setAuthentication(auth); + Page page = null; + do { + page = tweetRepository.getMyTweetsAndTheOnesILiked(new PageRequest(page != null ? page.getNumber() + 1 : 0, 5)); + for (Tweet twt : page.getContent()) { + isTrue((twt.getOwner() == appUser.getUsername()) || (twt.getLikes() + .contains(appUser.getUsername())), "I do not have any Tweets"); + } + } while (page.hasNext()); + } + + @Test(expected = InvalidDataAccessApiUsageException.class) + public void givenNoAppUser_whenPaginatedResultsRetrievalAttempted_shouldFail() { + Page page = null; + do { + page = tweetRepository.getMyTweetsAndTheOnesILiked(new PageRequest(page != null ? page.getNumber() + 1 : 0, 5)); + } while (page != null && page.hasNext()); + } +} From 53bb9276100b3714cdf08cc49de91e17dc172a7e Mon Sep 17 00:00:00 2001 From: Nam Thai Nguyen Date: Sat, 3 Feb 2018 20:21:46 +0700 Subject: [PATCH 27/28] Modifies the Data class --- .../main/java/com/baeldung/javac/Data.java | 24 +++++-------------- 1 file changed, 6 insertions(+), 18 deletions(-) diff --git a/core-java/src/main/java/com/baeldung/javac/Data.java b/core-java/src/main/java/com/baeldung/javac/Data.java index f6912fbd14..feef0c4f1e 100644 --- a/core-java/src/main/java/com/baeldung/javac/Data.java +++ b/core-java/src/main/java/com/baeldung/javac/Data.java @@ -1,28 +1,16 @@ package com.baeldung.javac; -import java.io.Serializable; import java.util.ArrayList; import java.util.List; -public class Data implements Serializable { - static List textList = new ArrayList(); +public class Data { + List textList = new ArrayList(); - private static void addText() { - textList.add("baeldung"); - textList.add("."); - textList.add("com"); + public void addText(String text) { + textList.add(text); } public List getTextList() { - this.addText(); - List result = new ArrayList(); - String firstElement = (String) textList.get(0); - switch (firstElement) { - case "baeldung": - result.add("baeldung"); - case "com": - result.add("com"); - } - return result; + return this.textList; } -} +} \ No newline at end of file From bf5b3045a1f6fe710a1ae63e935504a6139f05ba Mon Sep 17 00:00:00 2001 From: Eric Goebelbecker Date: Sat, 3 Feb 2018 22:49:11 -0500 Subject: [PATCH 28/28] BAEL-1486 - sample code for JGroups. Fixed a typo in InfluxDB. (#3578) --- influxdb/README.md | 1 - .../influxdb/InfluxDBConnectionLiveTest.java | 3 +- jgroups/README.md | 15 ++ jgroups/pom.xml | 36 +++ .../baeldung/jgroups/JGroupsMessenger.java | 222 ++++++++++++++++++ jgroups/src/main/resources/udp.xml | 48 ++++ pom.xml | 1 + 7 files changed, 323 insertions(+), 3 deletions(-) create mode 100644 jgroups/README.md create mode 100644 jgroups/pom.xml create mode 100644 jgroups/src/main/java/com/baeldung/jgroups/JGroupsMessenger.java create mode 100644 jgroups/src/main/resources/udp.xml diff --git a/influxdb/README.md b/influxdb/README.md index 7d1684688d..f2c421580e 100644 --- a/influxdb/README.md +++ b/influxdb/README.md @@ -2,7 +2,6 @@ ### Relevant Article: - [Introduction to using InfluxDB with Java](http://www.baeldung.com/using-influxdb-with-java/) -- [Using InfluxDB with Java](http://www.baeldung.com/java-influxdb) ### Overview This Maven project contains the Java code for the article linked above. diff --git a/influxdb/src/test/java/com/baeldung/influxdb/InfluxDBConnectionLiveTest.java b/influxdb/src/test/java/com/baeldung/influxdb/InfluxDBConnectionLiveTest.java index 6c7a03cb70..858903a676 100644 --- a/influxdb/src/test/java/com/baeldung/influxdb/InfluxDBConnectionLiveTest.java +++ b/influxdb/src/test/java/com/baeldung/influxdb/InfluxDBConnectionLiveTest.java @@ -8,7 +8,6 @@ import org.influxdb.dto.*; import org.influxdb.impl.InfluxDBResultMapper; import org.junit.Test; -import java.io.IOException; import java.util.List; import java.util.concurrent.TimeUnit; @@ -103,7 +102,7 @@ public class InfluxDBConnectionLiveTest { // another brief pause. Thread.sleep(10); - List memoryPointList = getPoints(connection, "Select * from memory", "baeldung"); + List memoryPointList = getPoints(connection, "Select * from memory", "baeldung"); assertEquals(10, memoryPointList.size()); diff --git a/jgroups/README.md b/jgroups/README.md new file mode 100644 index 0000000000..bb2813c3d6 --- /dev/null +++ b/jgroups/README.md @@ -0,0 +1,15 @@ +## Reliable Messaging with JGroups Tutorial Project + +### Relevant Article: +- [Reliable Messaging with JGroups](http://www.baeldung.com/reliable-messaging-with-jgroups/) + +### Overview +This Maven project contains the Java code for the article linked above. + +### Package Organization +Java classes for the intro tutorial are in the org.baeldung.jgroups package. + + +### Running the tests + +``` diff --git a/jgroups/pom.xml b/jgroups/pom.xml new file mode 100644 index 0000000000..0e5971875e --- /dev/null +++ b/jgroups/pom.xml @@ -0,0 +1,36 @@ + + + 4.0.0 + jgroups + 0.1-SNAPSHOT + jar + jgroups + Reliable Messaging with JGroups Tutorial + + + com.baeldung + parent-modules + 1.0.0-SNAPSHOT + + + + + org.jgroups + jgroups + 4.0.10.Final + + + + commons-cli + commons-cli + 1.4 + + + + + 1.8 + UTF-8 + + + diff --git a/jgroups/src/main/java/com/baeldung/jgroups/JGroupsMessenger.java b/jgroups/src/main/java/com/baeldung/jgroups/JGroupsMessenger.java new file mode 100644 index 0000000000..2a8df8a9ab --- /dev/null +++ b/jgroups/src/main/java/com/baeldung/jgroups/JGroupsMessenger.java @@ -0,0 +1,222 @@ +package com.baeldung.jgroups; + +import org.apache.commons.cli.*; +import org.jgroups.*; +import org.jgroups.util.Util; + +import java.io.*; +import java.util.List; +import java.util.Optional; + +public class JGroupsMessenger extends ReceiverAdapter { + + private JChannel channel; + private String userName; + private String clusterName; + private View lastView; + private boolean running = true; + + // Our shared state + private Integer messageCount = 0; + + /** + * Connect to a JGroups cluster using command line options + * @param args command line arguments + * @throws Exception + */ + private void start(String[] args) throws Exception { + processCommandline(args); + + // Create the channel + // This file could be moved, or made a command line option. + channel = new JChannel("src/main/resources/udp.xml"); + + // Set a name + channel.name(userName); + + // Register for callbacks + channel.setReceiver(this); + + // Ignore our messages + channel.setDiscardOwnMessages(true); + + // Connect + channel.connect(clusterName); + + // Start state transfer + channel.getState(null, 0); + + // Do the things + processInput(); + + // Clean up + channel.close(); + + } + + /** + * Quick and dirty implementaton of commons cli for command line args + * @param args the command line args + * @throws ParseException + */ + private void processCommandline(String[] args) throws ParseException { + + // Options, parser, friendly help + Options options = new Options(); + CommandLineParser parser = new DefaultParser(); + HelpFormatter formatter = new HelpFormatter(); + + options.addOption("u", "user", true, "User name") + .addOption("c", "cluster", true, "Cluster name"); + + CommandLine line = parser.parse(options, args); + + if (line.hasOption("user")) { + userName = line.getOptionValue("user"); + } else { + formatter.printHelp("JGroupsMessenger: need a user name.\n", options); + System.exit(-1); + } + + if (line.hasOption("cluster")) { + clusterName = line.getOptionValue("cluster"); + } else { + formatter.printHelp("JGroupsMessenger: need a cluster name.\n", options); + System.exit(-1); + } + } + + // Start it up + public static void main(String[] args) throws Exception { + new JGroupsMessenger().start(args); + } + + + @Override + public void viewAccepted(View newView) { + + // Save view if this is the first + if (lastView == null) { + System.out.println("Received initial view:"); + newView.forEach(System.out::println); + } else { + + // Compare to last view + System.out.println("Received new view."); + + List
newMembers = View.newMembers(lastView, newView); + if (newMembers.size() > 0) { + System.out.println("New members: "); + newMembers.forEach(System.out::println); + } + + List
exMembers = View.leftMembers(lastView, newView); + if (exMembers.size() > 0) { + System.out.println("Exited members:"); + exMembers.forEach(System.out::println); + } + } + lastView = newView; + } + + /** + * Loop on console input until we see 'x' to exit + */ + private void processInput() { + + BufferedReader in = new BufferedReader(new InputStreamReader(System.in)); + while (running) { + try { + + // Get a destination, means broadcast + Address destination = null; + System.out.print("Enter a destination: "); + System.out.flush(); + String destinationName = in.readLine().toLowerCase(); + + if (destinationName.equals("x")) { + running = false; + continue; + } else if (!destinationName.isEmpty()) { + Optional
optDestination = getAddress(destinationName); + if (optDestination.isPresent()) { + destination = optDestination.get(); + } else { + System.out.println("Destination not found, try again."); + continue; + } + } + + // Accept a string to send + System.out.print("Enter a message: "); + System.out.flush(); + String line = in.readLine().toLowerCase(); + sendMessage(destination, line); + } catch (IOException ioe) { + running = false; + } + } + System.out.println("Exiting."); + } + + /** + * Send message from here + * @param destination the destination + * @param messageString the message + */ + private void sendMessage(Address destination, String messageString) { + try { + System.out.println("Sending " + messageString + " to " + destination); + Message message = new Message(destination, messageString); + channel.send(message); + } catch (Exception exception) { + System.err.println("Exception sending message: " + exception.getMessage()); + running = false; + } + } + + @Override + public void receive(Message message) { + // Print source and dest with message + String line = "Message received from: " + message.getSrc() + " to: " + message.getDest() + " -> " + message.getObject(); + + // Only track the count of broadcast messages + // Tracking direct message would make for a pointless state + if (message.getDest() == null) { + messageCount++; + System.out.println("Message count: " + messageCount); + } + + System.out.println(line); + } + + @Override + public void getState(OutputStream output) throws Exception { + // Serialize into the stream + Util.objectToStream(messageCount, new DataOutputStream(output)); + } + + @Override + public void setState(InputStream input) { + + // NOTE: since we know that incrementing the count and transferring the state + // is done inside the JChannel's thread, we don't have to worry about synchronizing + // messageCount. For production code it should be synchronized! + try { + // Deserialize + messageCount = Util.objectFromStream(new DataInputStream(input)); + } catch (Exception e) { + System.out.println("Error deserialing state!"); + } + System.out.println(messageCount + " is the current messagecount."); + } + + + private Optional
getAddress(String name) { + View view = channel.view(); + return view.getMembers().stream().filter(address -> name.equals(address.toString())).findFirst(); + } + +} + + diff --git a/jgroups/src/main/resources/udp.xml b/jgroups/src/main/resources/udp.xml new file mode 100644 index 0000000000..5a9bfd0851 --- /dev/null +++ b/jgroups/src/main/resources/udp.xml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml index 582ee6696e..ca6d4afe82 100644 --- a/pom.xml +++ b/pom.xml @@ -93,6 +93,7 @@ javax-servlets javaxval jaxb + jgroups jee-7 jjwt