Merge remote-tracking branch 'upstream/master'
This commit is contained in:
commit
7ca9e6c383
|
@ -5,7 +5,7 @@ import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
public class KadaneAlgorithm {
|
public class KadaneAlgorithm {
|
||||||
|
|
||||||
private Logger logger = LoggerFactory.getLogger(BruteForceAlgorithm.class.getName());
|
private Logger logger = LoggerFactory.getLogger(KadaneAlgorithm.class.getName());
|
||||||
|
|
||||||
public int maxSubArraySum(int[] arr) {
|
public int maxSubArraySum(int[] arr) {
|
||||||
|
|
||||||
|
@ -14,15 +14,15 @@ public class KadaneAlgorithm {
|
||||||
int end = 0;
|
int end = 0;
|
||||||
|
|
||||||
int maxSoFar = arr[0], maxEndingHere = arr[0];
|
int maxSoFar = arr[0], maxEndingHere = arr[0];
|
||||||
|
|
||||||
for (int i = 1; i < size; i++) {
|
for (int i = 1; i < size; i++) {
|
||||||
|
maxEndingHere = maxEndingHere + arr[i];
|
||||||
if (arr[i] > maxEndingHere + arr[i]) {
|
if (arr[i] > maxEndingHere) {
|
||||||
start = i;
|
|
||||||
maxEndingHere = arr[i];
|
maxEndingHere = arr[i];
|
||||||
} else {
|
if (maxSoFar < maxEndingHere) {
|
||||||
maxEndingHere = maxEndingHere + arr[i];
|
start = i;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (maxSoFar < maxEndingHere) {
|
if (maxSoFar < maxEndingHere) {
|
||||||
maxSoFar = maxEndingHere;
|
maxSoFar = maxEndingHere;
|
||||||
end = i;
|
end = i;
|
||||||
|
|
|
@ -7,7 +7,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
class KadaneAlgorithmUnitTest {
|
class KadaneAlgorithmUnitTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void givenArrayWithNegativeNumberWhenMaximumSubarrayThenReturns6() {
|
void givenArrayWithNegativeNumberWhenMaximumSubarrayThenReturnsExpectedResult() {
|
||||||
//given
|
//given
|
||||||
int[] arr = new int[] { -3, 1, -8, 4, -1, 2, 1, -5, 5 };
|
int[] arr = new int[] { -3, 1, -8, 4, -1, 2, 1, -5, 5 };
|
||||||
//when
|
//when
|
||||||
|
@ -27,7 +27,7 @@ class KadaneAlgorithmUnitTest {
|
||||||
//then
|
//then
|
||||||
assertEquals(-1, maxSum);
|
assertEquals(-1, maxSum);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void givenArrayWithAllPosiitveNumbersWhenMaximumSubarrayThenReturnsExpectedResult() {
|
void givenArrayWithAllPosiitveNumbersWhenMaximumSubarrayThenReturnsExpectedResult() {
|
||||||
//given
|
//given
|
||||||
|
@ -39,4 +39,15 @@ class KadaneAlgorithmUnitTest {
|
||||||
assertEquals(10, maxSum);
|
assertEquals(10, maxSum);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void givenArrayToTestStartIndexWhenMaximumSubarrayThenReturnsExpectedResult() {
|
||||||
|
//given
|
||||||
|
int[] arr = new int[] { 1, 2, -1, 3, -6, -2 };
|
||||||
|
//when
|
||||||
|
KadaneAlgorithm algorithm = new KadaneAlgorithm();
|
||||||
|
int maxSum = algorithm.maxSubArraySum(arr);
|
||||||
|
//then
|
||||||
|
assertEquals(5, maxSum);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -3,4 +3,5 @@
|
||||||
- [Algorithm to Identify and Validate a Credit Card Number](https://www.baeldung.com/java-validate-cc-number)
|
- [Algorithm to Identify and Validate a Credit Card Number](https://www.baeldung.com/java-validate-cc-number)
|
||||||
- [Find the N Most Frequent Elements in a Java Array](https://www.baeldung.com/java-n-most-frequent-elements-array)
|
- [Find the N Most Frequent Elements in a Java Array](https://www.baeldung.com/java-n-most-frequent-elements-array)
|
||||||
- [Getting Pixel Array From Image in Java](https://www.baeldung.com/java-getting-pixel-array-from-image)
|
- [Getting Pixel Array From Image in Java](https://www.baeldung.com/java-getting-pixel-array-from-image)
|
||||||
|
- [Calculate Distance Between Two Coordinates in Java](https://www.baeldung.com/java-find-distance-between-points)
|
||||||
- More articles: [[<-- prev]](/algorithms-miscellaneous-6)
|
- More articles: [[<-- prev]](/algorithms-miscellaneous-6)
|
||||||
|
|
|
@ -1,7 +0,0 @@
|
||||||
## Annotations
|
|
||||||
|
|
||||||
This module contains articles about Java annotations
|
|
||||||
|
|
||||||
### Relevant Articles:
|
|
||||||
|
|
||||||
- [Java Annotation Processing and Creating a Builder](https://www.baeldung.com/java-annotation-processing-builder)
|
|
|
@ -1,21 +0,0 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
|
||||||
<modelVersion>4.0.0</modelVersion>
|
|
||||||
<artifactId>annotations</artifactId>
|
|
||||||
<name>annotations</name>
|
|
||||||
<packaging>pom</packaging>
|
|
||||||
|
|
||||||
<parent>
|
|
||||||
<groupId>com.baeldung</groupId>
|
|
||||||
<artifactId>parent-modules</artifactId>
|
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
|
||||||
</parent>
|
|
||||||
|
|
||||||
<modules>
|
|
||||||
<module>annotation-processing</module>
|
|
||||||
<module>annotation-user</module>
|
|
||||||
</modules>
|
|
||||||
|
|
||||||
</project>
|
|
|
@ -43,19 +43,19 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.sun.xml.ws</groupId>
|
<groupId>com.sun.xml.ws</groupId>
|
||||||
<artifactId>jaxws-ri</artifactId>
|
<artifactId>jaxws-ri</artifactId>
|
||||||
<version>2.3.3</version>
|
<version>${jaxws-ri.version}</version>
|
||||||
<type>pom</type>
|
<type>pom</type>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.servlet</groupId>
|
<groupId>javax.servlet</groupId>
|
||||||
<artifactId>javax.servlet-api</artifactId>
|
<artifactId>javax.servlet-api</artifactId>
|
||||||
<version>4.0.1</version>
|
<version>${javax.servlet-api.version}</version>
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>javax.servlet</groupId>
|
<groupId>javax.servlet</groupId>
|
||||||
<artifactId>jstl</artifactId>
|
<artifactId>jstl</artifactId>
|
||||||
<version>1.2</version>
|
<version>${jstl.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
@ -117,7 +117,9 @@
|
||||||
<properties>
|
<properties>
|
||||||
<spring.version>5.3.25</spring.version>
|
<spring.version>5.3.25</spring.version>
|
||||||
<cargo-maven2-plugin.version>1.6.1</cargo-maven2-plugin.version>
|
<cargo-maven2-plugin.version>1.6.1</cargo-maven2-plugin.version>
|
||||||
<maven-war-plugin.version>3.3.2</maven-war-plugin.version>
|
<jstl.version>1.2</jstl.version>
|
||||||
|
<javax.servlet-api.version>4.0.1</javax.servlet-api.version>
|
||||||
|
<jaxws-ri.version>2.3.3</jaxws-ri.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
|
@ -14,6 +14,7 @@ import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
|
||||||
import org.apache.hc.client5.http.impl.cookie.BasicClientCookie;
|
import org.apache.hc.client5.http.impl.cookie.BasicClientCookie;
|
||||||
import org.apache.hc.client5.http.protocol.HttpClientContext;
|
import org.apache.hc.client5.http.protocol.HttpClientContext;
|
||||||
|
|
||||||
|
import org.apache.http.cookie.ClientCookie;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
@ -51,8 +52,8 @@ class HttpClientGettingCookieValueUnitTest {
|
||||||
private BasicCookieStore createCustomCookieStore() {
|
private BasicCookieStore createCustomCookieStore() {
|
||||||
BasicCookieStore cookieStore = new BasicCookieStore();
|
BasicCookieStore cookieStore = new BasicCookieStore();
|
||||||
BasicClientCookie cookie = new BasicClientCookie("custom_cookie", "test_value");
|
BasicClientCookie cookie = new BasicClientCookie("custom_cookie", "test_value");
|
||||||
cookie.setDomain("baeldung.com");
|
cookie.setDomain("github.com");
|
||||||
cookie.setAttribute("domain", "true");
|
cookie.setAttribute(ClientCookie.DOMAIN_ATTR, "github.com");
|
||||||
cookie.setPath("/");
|
cookie.setPath("/");
|
||||||
cookieStore.addCookie(cookie);
|
cookieStore.addCookie(cookie);
|
||||||
return cookieStore;
|
return cookieStore;
|
||||||
|
|
|
@ -16,7 +16,7 @@ public class ApacheHttpClient5UnitTest {
|
||||||
public static final String DUMMY_URL = "https://postman-echo.com/get";
|
public static final String DUMMY_URL = "https://postman-echo.com/get";
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void whenUseApacheHttpClient_thenCorrect() throws IOException {
|
void whenUseApacheHttpClient_thenCorrect() throws IOException {
|
||||||
HttpGet request = new HttpGet(DUMMY_URL);
|
HttpGet request = new HttpGet(DUMMY_URL);
|
||||||
|
|
||||||
try (CloseableHttpClient client = HttpClients.createDefault()) {
|
try (CloseableHttpClient client = HttpClients.createDefault()) {
|
||||||
|
|
|
@ -1,6 +1,5 @@
|
||||||
package com.baeldung.httpclient.readresponsebodystring;
|
package com.baeldung.httpclient.readresponsebodystring;
|
||||||
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
|
@ -8,11 +7,13 @@ import java.net.http.HttpClient;
|
||||||
import java.net.http.HttpRequest;
|
import java.net.http.HttpRequest;
|
||||||
import java.net.http.HttpResponse;
|
import java.net.http.HttpResponse;
|
||||||
|
|
||||||
public class HttpClientUnitTest {
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class HttpClientUnitTest {
|
||||||
public static final String DUMMY_URL = "https://postman-echo.com/get";
|
public static final String DUMMY_URL = "https://postman-echo.com/get";
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void whenUseHttpClient_thenCorrect() throws IOException, InterruptedException {
|
void whenUseHttpClient_thenCorrect() throws IOException, InterruptedException {
|
||||||
HttpClient client = HttpClient.newHttpClient();
|
HttpClient client = HttpClient.newHttpClient();
|
||||||
HttpRequest request = HttpRequest.newBuilder().uri(URI.create(DUMMY_URL)).build();
|
HttpRequest request = HttpRequest.newBuilder().uri(URI.create(DUMMY_URL)).build();
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package com.baeldung.httpclient.readresponsebodystring;
|
package com.baeldung.httpclient.readresponsebodystring;
|
||||||
|
|
||||||
import org.junit.Assert;
|
|
||||||
import org.junit.Test;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -10,12 +10,14 @@ import java.io.InputStreamReader;
|
||||||
import java.net.HttpURLConnection;
|
import java.net.HttpURLConnection;
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
public class HttpUrlConnectionUnitTest {
|
public class HttpUrlConnectionUnitTest {
|
||||||
|
|
||||||
public static final String DUMMY_URL = "https://postman-echo.com/get";
|
public static final String DUMMY_URL = "https://postman-echo.com/get";
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void whenUseHttpUrlConnection_thenCorrect() throws IOException {
|
void whenUseHttpUrlConnection_thenCorrect() throws IOException {
|
||||||
HttpURLConnection connection = (HttpURLConnection) new URL(DUMMY_URL).openConnection();
|
HttpURLConnection connection = (HttpURLConnection) new URL(DUMMY_URL).openConnection();
|
||||||
|
|
||||||
InputStream inputStream = connection.getInputStream();
|
InputStream inputStream = connection.getInputStream();
|
||||||
|
@ -28,7 +30,7 @@ public class HttpUrlConnectionUnitTest {
|
||||||
response.append(currentLine);
|
response.append(currentLine);
|
||||||
|
|
||||||
in.close();
|
in.close();
|
||||||
Assert.assertNotNull(response.toString());
|
assertNotNull(response.toString());
|
||||||
System.out.println("Response -> " + response.toString());
|
System.out.println("Response -> " + response.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package com.baeldung.httpclient.readresponsebodystring;
|
package com.baeldung.httpclient.readresponsebodystring;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.web.client.RestTemplate;
|
import org.springframework.web.client.RestTemplate;
|
||||||
|
|
||||||
public class SpringRestTemplateUnitTest {
|
public class SpringRestTemplateUnitTest {
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
package com.baeldung.httpclient.readresponsebodystring;
|
package com.baeldung.httpclient.readresponsebodystring;
|
||||||
|
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.springframework.web.reactive.function.client.WebClient;
|
import org.springframework.web.reactive.function.client.WebClient;
|
||||||
import reactor.core.publisher.Mono;
|
import reactor.core.publisher.Mono;
|
||||||
|
|
||||||
|
@ -8,7 +8,7 @@ public class SpringWebClientUnitTest {
|
||||||
public static final String DUMMY_URL = "https://postman-echo.com/get";
|
public static final String DUMMY_URL = "https://postman-echo.com/get";
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void whenUseWebClientRetrieve_thenCorrect() {
|
void whenUseWebClientRetrieve_thenCorrect() {
|
||||||
WebClient webClient = WebClient.create(DUMMY_URL);
|
WebClient webClient = WebClient.create(DUMMY_URL);
|
||||||
Mono<String> body = webClient.get().retrieve().bodyToMono(String.class);
|
Mono<String> body = webClient.get().retrieve().bodyToMono(String.class);
|
||||||
String s = body.block();
|
String s = body.block();
|
||||||
|
|
|
@ -4,6 +4,7 @@
|
||||||
<pattern>%date [%level] %logger - %msg %n</pattern>
|
<pattern>%date [%level] %logger - %msg %n</pattern>
|
||||||
</encoder>
|
</encoder>
|
||||||
</appender>
|
</appender>
|
||||||
|
<logger name="com.baeldung.httpclient.cookies" level="info"/>
|
||||||
|
|
||||||
<logger name="com.baeldung.httpclient.readresponsebodystring" level="debug"/>
|
<logger name="com.baeldung.httpclient.readresponsebodystring" level="debug"/>
|
||||||
<logger name="org.apache.http" level="debug"/>
|
<logger name="org.apache.http" level="debug"/>
|
||||||
|
|
|
@ -15,45 +15,6 @@
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
<!-- http client -->
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.httpcomponents</groupId>
|
|
||||||
<artifactId>httpclient</artifactId>
|
|
||||||
<version>${httpclient.version}</version>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<artifactId>commons-logging</artifactId>
|
|
||||||
<groupId>commons-logging</groupId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.httpcomponents</groupId>
|
|
||||||
<artifactId>fluent-hc</artifactId>
|
|
||||||
<version>${httpclient.version}</version>
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<artifactId>commons-logging</artifactId>
|
|
||||||
<groupId>commons-logging</groupId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.httpcomponents</groupId>
|
|
||||||
<artifactId>httpmime</artifactId>
|
|
||||||
<version>${httpclient.version}</version>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.apache.httpcomponents</groupId>
|
|
||||||
<artifactId>httpasyncclient</artifactId>
|
|
||||||
<version>${httpasyncclient.version}</version> <!-- 4.0.2 --> <!-- 4.1-beta1 -->
|
|
||||||
<exclusions>
|
|
||||||
<exclusion>
|
|
||||||
<artifactId>commons-logging</artifactId>
|
|
||||||
<groupId>commons-logging</groupId>
|
|
||||||
</exclusion>
|
|
||||||
</exclusions>
|
|
||||||
</dependency>
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.apache.httpcomponents.core5</groupId>
|
<groupId>org.apache.httpcomponents.core5</groupId>
|
||||||
<artifactId>httpcore5</artifactId>
|
<artifactId>httpcore5</artifactId>
|
||||||
|
@ -115,12 +76,8 @@
|
||||||
</build>
|
</build>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<!-- util -->
|
|
||||||
<httpasyncclient.version>4.1.4</httpasyncclient.version>
|
|
||||||
<!-- testing -->
|
|
||||||
<mockserver.version>5.6.1</mockserver.version>
|
<mockserver.version>5.6.1</mockserver.version>
|
||||||
<wiremock.version>2.5.1</wiremock.version>
|
<wiremock.version>2.5.1</wiremock.version>
|
||||||
<httpclient.version>4.5.8</httpclient.version> <!-- 4.3.6 --> <!-- 4.4-beta1 -->
|
|
||||||
<!-- http client & core 5 -->
|
<!-- http client & core 5 -->
|
||||||
<httpcore5.version>5.2</httpcore5.version>
|
<httpcore5.version>5.2</httpcore5.version>
|
||||||
<httpclient5.version>5.2</httpclient5.version>
|
<httpclient5.version>5.2</httpclient5.version>
|
||||||
|
|
|
@ -4,10 +4,10 @@ import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
import org.apache.hc.core5.http.ParseException;
|
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
|
||||||
import org.apache.hc.client5.http.classic.methods.HttpPost;
|
import org.apache.hc.client5.http.classic.methods.HttpPost;
|
||||||
import org.apache.hc.client5.http.entity.mime.FileBody;
|
import org.apache.hc.client5.http.entity.mime.FileBody;
|
||||||
import org.apache.hc.client5.http.entity.mime.HttpMultipartMode;
|
import org.apache.hc.client5.http.entity.mime.HttpMultipartMode;
|
||||||
|
@ -19,6 +19,7 @@ import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
|
||||||
import org.apache.hc.core5.http.ContentType;
|
import org.apache.hc.core5.http.ContentType;
|
||||||
import org.apache.hc.core5.http.HttpEntity;
|
import org.apache.hc.core5.http.HttpEntity;
|
||||||
import org.apache.hc.core5.http.HttpStatus;
|
import org.apache.hc.core5.http.HttpStatus;
|
||||||
|
import org.apache.hc.core5.http.ParseException;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.BufferedReader;
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
@ -30,9 +31,6 @@ import java.net.URL;
|
||||||
|
|
||||||
class HttpClientMultipartLiveTest extends GetRequestMockServer {
|
class HttpClientMultipartLiveTest extends GetRequestMockServer {
|
||||||
|
|
||||||
// No longer available
|
|
||||||
// private static final String SERVER = "http://echo.200please.com";
|
|
||||||
|
|
||||||
private static final String SERVER = "http://localhost:8080/spring-mvc-java/stub/multipart";
|
private static final String SERVER = "http://localhost:8080/spring-mvc-java/stub/multipart";
|
||||||
private static final String TEXTFILENAME = "temp.txt";
|
private static final String TEXTFILENAME = "temp.txt";
|
||||||
private static final String IMAGEFILENAME = "image.jpg";
|
private static final String IMAGEFILENAME = "image.jpg";
|
||||||
|
|
|
@ -1,15 +1,16 @@
|
||||||
package com.baeldung.httpclient;
|
package com.baeldung.httpclient;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import org.apache.hc.client5.http.classic.methods.HttpGet;
|
import org.apache.hc.client5.http.classic.methods.HttpGet;
|
||||||
import org.apache.hc.client5.http.classic.methods.HttpPost;
|
import org.apache.hc.client5.http.classic.methods.HttpPost;
|
||||||
import org.apache.hc.client5.http.impl.DefaultRedirectStrategy;
|
import org.apache.hc.client5.http.impl.DefaultRedirectStrategy;
|
||||||
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
||||||
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
|
import org.apache.hc.client5.http.impl.classic.HttpClientBuilder;
|
||||||
import org.apache.hc.client5.http.impl.classic.HttpClients;
|
import org.apache.hc.client5.http.impl.classic.HttpClients;
|
||||||
import org.junit.jupiter.api.Test;
|
|
||||||
|
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
|
|
@ -8,7 +8,7 @@ import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor;
|
||||||
import static com.github.tomakehurst.wiremock.client.WireMock.post;
|
import static com.github.tomakehurst.wiremock.client.WireMock.post;
|
||||||
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
|
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
|
||||||
import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching;
|
import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@ -29,21 +29,34 @@ import org.apache.hc.core5.http.HttpHeaders;
|
||||||
import org.apache.hc.core5.http.HttpHost;
|
import org.apache.hc.core5.http.HttpHost;
|
||||||
import org.apache.hc.core5.http.HttpResponse;
|
import org.apache.hc.core5.http.HttpResponse;
|
||||||
import org.apache.hc.core5.http.io.entity.StringEntity;
|
import org.apache.hc.core5.http.io.entity.StringEntity;
|
||||||
import org.junit.Rule;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import com.github.tomakehurst.wiremock.junit.WireMockRule;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
public class HttpClientAdvancedConfigurationIntegrationTest {
|
import com.github.tomakehurst.wiremock.WireMockServer;
|
||||||
|
|
||||||
@Rule
|
class HttpClientAdvancedConfigurationIntegrationTest {
|
||||||
public WireMockRule serviceMock = new WireMockRule(8089);
|
|
||||||
|
|
||||||
@Rule
|
public WireMockServer serviceMock;
|
||||||
public WireMockRule proxyMock = new WireMockRule(8090);
|
public WireMockServer proxyMock;
|
||||||
|
|
||||||
|
@BeforeEach
|
||||||
|
public void before () {
|
||||||
|
serviceMock = new WireMockServer(8089);
|
||||||
|
serviceMock.start();
|
||||||
|
proxyMock = new WireMockServer(8090);
|
||||||
|
proxyMock.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void after () {
|
||||||
|
serviceMock.stop();
|
||||||
|
proxyMock.stop();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenClientWithCustomUserAgentHeader_whenExecuteRequest_shouldReturn200() throws IOException {
|
void givenClientWithCustomUserAgentHeader_whenExecuteRequest_shouldReturn200() throws IOException {
|
||||||
//given
|
//given
|
||||||
String userAgent = "BaeldungAgent/1.0";
|
String userAgent = "BaeldungAgent/1.0";
|
||||||
serviceMock.stubFor(get(urlEqualTo("/detail"))
|
serviceMock.stubFor(get(urlEqualTo("/detail"))
|
||||||
|
@ -59,11 +72,11 @@ public class HttpClientAdvancedConfigurationIntegrationTest {
|
||||||
HttpResponse response = httpClient.execute(httpGet);
|
HttpResponse response = httpClient.execute(httpGet);
|
||||||
|
|
||||||
//then
|
//then
|
||||||
assertEquals(response.getCode(), 200);
|
assertEquals(200, response.getCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenClientThatSendDataInBody_whenSendXmlInBody_shouldReturn200() throws IOException {
|
void givenClientThatSendDataInBody_whenSendXmlInBody_shouldReturn200() throws IOException {
|
||||||
//given
|
//given
|
||||||
String xmlBody = "<xml><id>1</id></xml>";
|
String xmlBody = "<xml><id>1</id></xml>";
|
||||||
serviceMock.stubFor(post(urlEqualTo("/person"))
|
serviceMock.stubFor(post(urlEqualTo("/person"))
|
||||||
|
@ -82,12 +95,12 @@ public class HttpClientAdvancedConfigurationIntegrationTest {
|
||||||
HttpResponse response = httpClient.execute(httpPost);
|
HttpResponse response = httpClient.execute(httpPost);
|
||||||
|
|
||||||
//then
|
//then
|
||||||
assertEquals(response.getCode(), 200);
|
assertEquals(200, response.getCode());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenServerThatIsBehindProxy_whenClientIsConfiguredToSendRequestViaProxy_shouldReturn200() throws IOException {
|
void givenServerThatIsBehindProxy_whenClientIsConfiguredToSendRequestViaProxy_shouldReturn200() throws IOException {
|
||||||
//given
|
//given
|
||||||
proxyMock.stubFor(get(urlMatching(".*"))
|
proxyMock.stubFor(get(urlMatching(".*"))
|
||||||
.willReturn(aResponse().proxiedFrom("http://localhost:8089/")));
|
.willReturn(aResponse().proxiedFrom("http://localhost:8089/")));
|
||||||
|
@ -107,7 +120,7 @@ public class HttpClientAdvancedConfigurationIntegrationTest {
|
||||||
HttpResponse response = httpclient.execute(httpGet);
|
HttpResponse response = httpclient.execute(httpGet);
|
||||||
|
|
||||||
//then
|
//then
|
||||||
assertEquals(response.getCode(), 200);
|
assertEquals(200, response.getCode());
|
||||||
proxyMock.verify(getRequestedFor(urlEqualTo("/private")));
|
proxyMock.verify(getRequestedFor(urlEqualTo("/private")));
|
||||||
serviceMock.verify(getRequestedFor(urlEqualTo("/private")));
|
serviceMock.verify(getRequestedFor(urlEqualTo("/private")));
|
||||||
}
|
}
|
||||||
|
@ -151,7 +164,7 @@ public class HttpClientAdvancedConfigurationIntegrationTest {
|
||||||
HttpResponse response = httpclient.execute(httpGet, context);
|
HttpResponse response = httpclient.execute(httpGet, context);
|
||||||
|
|
||||||
//then
|
//then
|
||||||
assertEquals(response.getCode(), 200);
|
assertEquals(200, response.getCode());
|
||||||
proxyMock.verify(getRequestedFor(urlEqualTo("/private")).withHeader("Authorization", containing("Basic")));
|
proxyMock.verify(getRequestedFor(urlEqualTo("/private")).withHeader("Authorization", containing("Basic")));
|
||||||
serviceMock.verify(getRequestedFor(urlEqualTo("/private")));
|
serviceMock.verify(getRequestedFor(urlEqualTo("/private")));
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,59 +0,0 @@
|
||||||
package com.baeldung.httpclient.base;
|
|
||||||
|
|
||||||
import com.baeldung.httpclient.ResponseUtil;
|
|
||||||
import org.apache.http.auth.AuthenticationException;
|
|
||||||
import org.apache.http.auth.UsernamePasswordCredentials;
|
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
|
||||||
import org.apache.http.client.methods.HttpPost;
|
|
||||||
import org.apache.http.entity.StringEntity;
|
|
||||||
import org.apache.http.impl.auth.BasicScheme;
|
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
|
||||||
import org.apache.http.impl.client.HttpClientBuilder;
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
public class HttpClientBasicPostLiveTest {
|
|
||||||
|
|
||||||
private static final String SAMPLE_URL = "http://www.github.com";
|
|
||||||
|
|
||||||
private CloseableHttpClient instance;
|
|
||||||
|
|
||||||
private CloseableHttpResponse response;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public final void before() {
|
|
||||||
instance = HttpClientBuilder.create().build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public final void after() throws IllegalStateException, IOException {
|
|
||||||
ResponseUtil.closeResponse(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// tests - non-GET
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public final void whenExecutingPostRequest_thenNoExceptions() throws IOException {
|
|
||||||
instance.execute(new HttpPost(SAMPLE_URL));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public final void whenExecutingPostRequestWithBody_thenNoExceptions() throws IOException {
|
|
||||||
final HttpPost request = new HttpPost(SAMPLE_URL);
|
|
||||||
request.setEntity(new StringEntity("in the body of the POST"));
|
|
||||||
instance.execute(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public final void givenAuth_whenExecutingPostRequestWithBody_thenNoExceptions() throws IOException, AuthenticationException {
|
|
||||||
final HttpPost request = new HttpPost(SAMPLE_URL);
|
|
||||||
request.setEntity(new StringEntity("in the body of the POST"));
|
|
||||||
final UsernamePasswordCredentials creds = new UsernamePasswordCredentials("username", "password");
|
|
||||||
request.addHeader(new BasicScheme().authenticate(creds, request, null));
|
|
||||||
instance.execute(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,75 +0,0 @@
|
||||||
package com.baeldung.httpclient.base;
|
|
||||||
|
|
||||||
import com.baeldung.httpclient.ResponseUtil;
|
|
||||||
|
|
||||||
import org.apache.http.Header;
|
|
||||||
import org.apache.http.HttpHeaders;
|
|
||||||
import org.apache.http.client.config.RequestConfig;
|
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
|
||||||
import org.apache.http.client.methods.HttpGet;
|
|
||||||
import org.apache.http.conn.ConnectTimeoutException;
|
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
|
||||||
import org.apache.http.impl.client.HttpClientBuilder;
|
|
||||||
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
|
|
||||||
import org.junit.After;
|
|
||||||
import org.junit.Before;
|
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
|
||||||
|
|
||||||
import static org.hamcrest.Matchers.emptyArray;
|
|
||||||
import static org.hamcrest.Matchers.not;
|
|
||||||
import static org.junit.Assert.assertThat;
|
|
||||||
|
|
||||||
public class HttpClientLiveTest {
|
|
||||||
|
|
||||||
private static final String SAMPLE_URL = "http://www.github.com";
|
|
||||||
|
|
||||||
private CloseableHttpClient instance;
|
|
||||||
|
|
||||||
private CloseableHttpResponse response;
|
|
||||||
|
|
||||||
@Before
|
|
||||||
public final void before() {
|
|
||||||
instance = HttpClientBuilder.create().build();
|
|
||||||
}
|
|
||||||
|
|
||||||
@After
|
|
||||||
public final void after() throws IllegalStateException, IOException {
|
|
||||||
ResponseUtil.closeResponse(response);
|
|
||||||
}
|
|
||||||
|
|
||||||
// tests
|
|
||||||
|
|
||||||
@Test(expected = ConnectTimeoutException.class)
|
|
||||||
public final void givenLowTimeout_whenExecutingRequestWithTimeout_thenException() throws IOException {
|
|
||||||
final RequestConfig requestConfig = RequestConfig.custom().setConnectionRequestTimeout(5).setConnectTimeout(5).setSocketTimeout(2).build();
|
|
||||||
final HttpGet request = new HttpGet(SAMPLE_URL);
|
|
||||||
request.setConfig(requestConfig);
|
|
||||||
response = instance.execute(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
// tests - configs
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public final void givenHttpClientIsConfiguredWithCustomConnectionManager_whenExecutingRequest_thenNoExceptions() throws IOException {
|
|
||||||
instance = HttpClientBuilder.create().setConnectionManager(new BasicHttpClientConnectionManager()).build();
|
|
||||||
response = instance.execute(new HttpGet(SAMPLE_URL));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public final void givenCustomHeaderIsSet_whenSendingRequest_thenNoExceptions() throws IOException {
|
|
||||||
final HttpGet request = new HttpGet(SAMPLE_URL);
|
|
||||||
request.addHeader(HttpHeaders.ACCEPT, "application/xml");
|
|
||||||
response = instance.execute(request);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Test
|
|
||||||
public final void givenRequestWasSet_whenAnalyzingTheHeadersOfTheResponse_thenCorrect() throws IOException {
|
|
||||||
response = instance.execute(new HttpGet(SAMPLE_URL));
|
|
||||||
|
|
||||||
final Header[] headers = response.getHeaders(HttpHeaders.CONTENT_TYPE);
|
|
||||||
assertThat(headers, not(emptyArray()));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -1,5 +1,6 @@
|
||||||
package com.baeldung.httpclient.conn;
|
package com.baeldung.httpclient.conn;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
@ -34,14 +35,13 @@ import org.apache.hc.core5.pool.PoolStats;
|
||||||
import org.apache.hc.core5.util.Args;
|
import org.apache.hc.core5.util.Args;
|
||||||
import org.apache.hc.core5.util.TimeValue;
|
import org.apache.hc.core5.util.TimeValue;
|
||||||
import org.apache.hc.core5.util.Timeout;
|
import org.apache.hc.core5.util.Timeout;
|
||||||
import org.junit.Assert;
|
import org.junit.jupiter.api.Test;
|
||||||
import org.junit.Test;
|
|
||||||
|
|
||||||
public class HttpClientConnectionManagementLiveTest {
|
class HttpClientConnectionManagementLiveTest {
|
||||||
|
|
||||||
// Example 2.1. Getting a Connection Request for a Low Level Connection (HttpClientConnection)
|
// Example 2.1. Getting a Connection Request for a Low Level Connection (HttpClientConnection)
|
||||||
@Test
|
@Test
|
||||||
public final void whenLowLevelConnectionIsEstablished_thenNoExceptions() throws ExecutionException, InterruptedException, TimeoutException {
|
final void whenLowLevelConnectionIsEstablished_thenNoExceptions() throws ExecutionException, InterruptedException, TimeoutException {
|
||||||
BasicHttpClientConnectionManager connMgr = new BasicHttpClientConnectionManager();
|
BasicHttpClientConnectionManager connMgr = new BasicHttpClientConnectionManager();
|
||||||
HttpRoute route = new HttpRoute(new HttpHost("www.baeldung.com", 443));
|
HttpRoute route = new HttpRoute(new HttpHost("www.baeldung.com", 443));
|
||||||
final LeaseRequest connRequest = connMgr.lease("some-id", route, null);
|
final LeaseRequest connRequest = connMgr.lease("some-id", route, null);
|
||||||
|
@ -51,7 +51,7 @@ public class HttpClientConnectionManagementLiveTest {
|
||||||
|
|
||||||
// Example 3.1. Setting the PoolingHttpClientConnectionManager on a HttpClient
|
// Example 3.1. Setting the PoolingHttpClientConnectionManager on a HttpClient
|
||||||
@Test
|
@Test
|
||||||
public final void whenPollingConnectionManagerIsConfiguredOnHttpClient_thenNoExceptions() throws IOException {
|
final void whenPollingConnectionManagerIsConfiguredOnHttpClient_thenNoExceptions() throws IOException {
|
||||||
PoolingHttpClientConnectionManager poolingConnManager = new PoolingHttpClientConnectionManager();
|
PoolingHttpClientConnectionManager poolingConnManager = new PoolingHttpClientConnectionManager();
|
||||||
CloseableHttpClient client = HttpClients.custom()
|
CloseableHttpClient client = HttpClients.custom()
|
||||||
.setConnectionManager(poolingConnManager)
|
.setConnectionManager(poolingConnManager)
|
||||||
|
@ -65,7 +65,7 @@ public class HttpClientConnectionManagementLiveTest {
|
||||||
|
|
||||||
// Example 3.2. Using Two HttpClients to Connect to One Target Host Each
|
// Example 3.2. Using Two HttpClients to Connect to One Target Host Each
|
||||||
@Test
|
@Test
|
||||||
public final void whenTwoConnectionsForTwoRequests_thenNoExceptions() throws InterruptedException, IOException {
|
final void whenTwoConnectionsForTwoRequests_thenNoExceptions() throws InterruptedException, IOException {
|
||||||
HttpGet get1 = new HttpGet("https://www.baeldung.com");
|
HttpGet get1 = new HttpGet("https://www.baeldung.com");
|
||||||
HttpGet get2 = new HttpGet("https://www.google.com");
|
HttpGet get2 = new HttpGet("https://www.google.com");
|
||||||
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
|
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
|
||||||
|
@ -83,8 +83,7 @@ public class HttpClientConnectionManagementLiveTest {
|
||||||
thread1.join();
|
thread1.join();
|
||||||
thread2.join();
|
thread2.join();
|
||||||
|
|
||||||
Assert.assertTrue(connManager.getTotalStats()
|
assertEquals(0, connManager.getTotalStats().getLeased());
|
||||||
.getLeased() == 0);
|
|
||||||
client1.close();
|
client1.close();
|
||||||
client2.close();
|
client2.close();
|
||||||
connManager.close();
|
connManager.close();
|
||||||
|
@ -92,7 +91,7 @@ public class HttpClientConnectionManagementLiveTest {
|
||||||
|
|
||||||
// Example 4.1. Increasing the Number of Connections that Can be Open and Managed Beyond the default Limits
|
// Example 4.1. Increasing the Number of Connections that Can be Open and Managed Beyond the default Limits
|
||||||
@Test
|
@Test
|
||||||
public final void whenIncreasingConnectionPool_thenNoExceptions() {
|
final void whenIncreasingConnectionPool_thenNoExceptions() {
|
||||||
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
|
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
|
||||||
connManager.setMaxTotal(5);
|
connManager.setMaxTotal(5);
|
||||||
connManager.setDefaultMaxPerRoute(4);
|
connManager.setDefaultMaxPerRoute(4);
|
||||||
|
@ -103,7 +102,7 @@ public class HttpClientConnectionManagementLiveTest {
|
||||||
|
|
||||||
// Example 4.2. Using Threads to Execute Connections
|
// Example 4.2. Using Threads to Execute Connections
|
||||||
@Test
|
@Test
|
||||||
public final void whenExecutingSameRequestsInDifferentThreads_thenExecuteRequest() throws InterruptedException, IOException {
|
final void whenExecutingSameRequestsInDifferentThreads_thenExecuteRequest() throws InterruptedException, IOException {
|
||||||
HttpGet get = new HttpGet("http://www.baeldung.com");
|
HttpGet get = new HttpGet("http://www.baeldung.com");
|
||||||
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
|
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
|
||||||
CloseableHttpClient client = HttpClients.custom()
|
CloseableHttpClient client = HttpClients.custom()
|
||||||
|
@ -133,7 +132,7 @@ public class HttpClientConnectionManagementLiveTest {
|
||||||
|
|
||||||
// Example 5.1. A Custom Keep Alive Strategy
|
// Example 5.1. A Custom Keep Alive Strategy
|
||||||
@Test
|
@Test
|
||||||
public final void whenCustomizingKeepAliveStrategy_thenNoExceptions() {
|
final void whenCustomizingKeepAliveStrategy_thenNoExceptions() {
|
||||||
final ConnectionKeepAliveStrategy myStrategy = new ConnectionKeepAliveStrategy() {
|
final ConnectionKeepAliveStrategy myStrategy = new ConnectionKeepAliveStrategy() {
|
||||||
@Override
|
@Override
|
||||||
public TimeValue getKeepAliveDuration(HttpResponse response, HttpContext context) {
|
public TimeValue getKeepAliveDuration(HttpResponse response, HttpContext context) {
|
||||||
|
@ -162,7 +161,7 @@ public class HttpClientConnectionManagementLiveTest {
|
||||||
|
|
||||||
//Example 6.1. BasicHttpClientConnectionManager Connection Reuse
|
//Example 6.1. BasicHttpClientConnectionManager Connection Reuse
|
||||||
@Test
|
@Test
|
||||||
public final void givenBasicHttpClientConnManager_whenConnectionReuse_thenNoExceptions() throws InterruptedException, ExecutionException, TimeoutException, IOException, URISyntaxException {
|
final void givenBasicHttpClientConnManager_whenConnectionReuse_thenNoExceptions() throws InterruptedException, ExecutionException, TimeoutException, IOException, URISyntaxException {
|
||||||
BasicHttpClientConnectionManager connMgr = new BasicHttpClientConnectionManager();
|
BasicHttpClientConnectionManager connMgr = new BasicHttpClientConnectionManager();
|
||||||
HttpRoute route = new HttpRoute(new HttpHost("www.baeldung.com", 443));
|
HttpRoute route = new HttpRoute(new HttpHost("www.baeldung.com", 443));
|
||||||
final HttpContext context = new BasicHttpContext();
|
final HttpContext context = new BasicHttpContext();
|
||||||
|
@ -184,7 +183,7 @@ public class HttpClientConnectionManagementLiveTest {
|
||||||
|
|
||||||
// Example 6.2. PoolingHttpClientConnectionManager: Re-Using Connections with Threads
|
// Example 6.2. PoolingHttpClientConnectionManager: Re-Using Connections with Threads
|
||||||
@Test
|
@Test
|
||||||
public final void whenConnectionsNeededGreaterThanMaxTotal_thenLeaseMasTotalandReuse() throws InterruptedException, IOException {
|
final void whenConnectionsNeededGreaterThanMaxTotal_thenLeaseMasTotalandReuse() throws InterruptedException, IOException {
|
||||||
HttpGet get = new HttpGet("http://www.baeldung.com");
|
HttpGet get = new HttpGet("http://www.baeldung.com");
|
||||||
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
|
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
|
||||||
connManager.setDefaultMaxPerRoute(6);
|
connManager.setDefaultMaxPerRoute(6);
|
||||||
|
@ -208,7 +207,7 @@ public class HttpClientConnectionManagementLiveTest {
|
||||||
|
|
||||||
// Example 7.1. Setting Socket Timeout to 5 Seconds
|
// Example 7.1. Setting Socket Timeout to 5 Seconds
|
||||||
@Test
|
@Test
|
||||||
public final void whenConfiguringTimeOut_thenNoExceptions() throws ExecutionException, InterruptedException, TimeoutException, IOException {
|
final void whenConfiguringTimeOut_thenNoExceptions() throws ExecutionException, InterruptedException, TimeoutException, IOException {
|
||||||
final HttpRoute route = new HttpRoute(new HttpHost("www.baeldung.com", 80));
|
final HttpRoute route = new HttpRoute(new HttpHost("www.baeldung.com", 80));
|
||||||
final HttpContext context = new BasicHttpContext();
|
final HttpContext context = new BasicHttpContext();
|
||||||
final PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
|
final PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
|
||||||
|
@ -227,7 +226,7 @@ public class HttpClientConnectionManagementLiveTest {
|
||||||
|
|
||||||
// Example 8.1. Setting the HttpClient to Check for Stale Connections
|
// Example 8.1. Setting the HttpClient to Check for Stale Connections
|
||||||
@Test
|
@Test
|
||||||
public final void whenEvictIdealConn_thenNoExceptions() throws InterruptedException, IOException {
|
final void whenEvictIdealConn_thenNoExceptions() throws InterruptedException, IOException {
|
||||||
final PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
|
final PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
|
||||||
connManager.setMaxTotal(100);
|
connManager.setMaxTotal(100);
|
||||||
try (final CloseableHttpClient httpclient = HttpClients.custom()
|
try (final CloseableHttpClient httpclient = HttpClients.custom()
|
||||||
|
@ -266,7 +265,7 @@ public class HttpClientConnectionManagementLiveTest {
|
||||||
|
|
||||||
// Example 9.1. Closing Connection and Releasing Resources
|
// Example 9.1. Closing Connection and Releasing Resources
|
||||||
@Test
|
@Test
|
||||||
public final void whenClosingConnectionsandManager_thenCloseWithNoExceptions1() throws IOException {
|
final void whenClosingConnectionsAndManager_thenCloseWithNoExceptions1() throws IOException {
|
||||||
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
|
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
|
||||||
CloseableHttpClient client = HttpClients.custom()
|
CloseableHttpClient client = HttpClients.custom()
|
||||||
.setConnectionManager(connManager)
|
.setConnectionManager(connManager)
|
||||||
|
@ -282,7 +281,7 @@ public class HttpClientConnectionManagementLiveTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
// Example 3.2. TESTER VERSION
|
// Example 3.2. TESTER VERSION
|
||||||
public final void whenTwoConnectionsForTwoRequests_thenTwoConnectionsAreLeased() throws InterruptedException, IOException {
|
final void whenTwoConnectionsForTwoRequests_thenTwoConnectionsAreLeased() throws InterruptedException, IOException {
|
||||||
HttpGet get1 = new HttpGet("https://www.baeldung.com");
|
HttpGet get1 = new HttpGet("https://www.baeldung.com");
|
||||||
HttpGet get2 = new HttpGet("https://www.google.com");
|
HttpGet get2 = new HttpGet("https://www.google.com");
|
||||||
|
|
||||||
|
@ -300,8 +299,7 @@ public class HttpClientConnectionManagementLiveTest {
|
||||||
thread2.start();
|
thread2.start();
|
||||||
thread1.join();
|
thread1.join();
|
||||||
thread2.join(1000);
|
thread2.join(1000);
|
||||||
Assert.assertTrue(poolingConnManager.getTotalStats()
|
assertEquals(2, poolingConnManager.getTotalStats().getLeased());
|
||||||
.getLeased() == 2);
|
|
||||||
|
|
||||||
client1.close();
|
client1.close();
|
||||||
client2.close();
|
client2.close();
|
||||||
|
|
|
@ -1,41 +0,0 @@
|
||||||
package com.baeldung.httpclient.conn;
|
|
||||||
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
|
|
||||||
import org.apache.http.conn.HttpClientConnectionManager;
|
|
||||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
|
||||||
|
|
||||||
public class IdleConnectionMonitorThread extends Thread {
|
|
||||||
private final HttpClientConnectionManager connMgr;
|
|
||||||
private volatile boolean shutdown;
|
|
||||||
|
|
||||||
IdleConnectionMonitorThread(final PoolingHttpClientConnectionManager connMgr) {
|
|
||||||
super();
|
|
||||||
this.connMgr = connMgr;
|
|
||||||
}
|
|
||||||
|
|
||||||
// API
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void run() {
|
|
||||||
try {
|
|
||||||
while (!shutdown) {
|
|
||||||
synchronized (this) {
|
|
||||||
wait(1000);
|
|
||||||
connMgr.closeExpiredConnections();
|
|
||||||
connMgr.closeIdleConnections(30, TimeUnit.SECONDS);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (final InterruptedException ex) {
|
|
||||||
shutdown();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void shutdown() {
|
|
||||||
shutdown = true;
|
|
||||||
synchronized (this) {
|
|
||||||
notifyAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -6,7 +6,6 @@ import org.apache.hc.client5.http.classic.methods.HttpGet;
|
||||||
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
import org.apache.hc.client5.http.impl.classic.CloseableHttpClient;
|
||||||
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
|
import org.apache.hc.client5.http.impl.io.PoolingHttpClientConnectionManager;
|
||||||
import org.apache.hc.core5.http.HttpEntity;
|
import org.apache.hc.core5.http.HttpEntity;
|
||||||
import org.apache.hc.core5.http.HttpResponse;
|
|
||||||
import org.apache.hc.core5.http.io.entity.EntityUtils;
|
import org.apache.hc.core5.http.io.entity.EntityUtils;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
|
@ -241,8 +241,6 @@
|
||||||
<httpcore.version>4.4.16</httpcore.version>
|
<httpcore.version>4.4.16</httpcore.version>
|
||||||
<httpclient.version>4.5.14</httpclient.version>
|
<httpclient.version>4.5.14</httpclient.version>
|
||||||
<mockserver.version>5.11.2</mockserver.version>
|
<mockserver.version>5.11.2</mockserver.version>
|
||||||
<!-- maven plugins -->
|
|
||||||
<maven-war-plugin.version>3.3.2</maven-war-plugin.version>
|
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
|
@ -1,7 +1,7 @@
|
||||||
package com.baeldung.httpclient.base;
|
package com.baeldung.client;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
import com.baeldung.httpclient.GetRequestMockServer;
|
|
||||||
import com.baeldung.httpclient.ResponseUtil;
|
|
||||||
import org.apache.http.auth.AuthScope;
|
import org.apache.http.auth.AuthScope;
|
||||||
import org.apache.http.auth.UsernamePasswordCredentials;
|
import org.apache.http.auth.UsernamePasswordCredentials;
|
||||||
import org.apache.http.client.CredentialsProvider;
|
import org.apache.http.client.CredentialsProvider;
|
||||||
|
@ -12,15 +12,16 @@ import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
import org.apache.http.impl.client.HttpClientBuilder;
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.io.IOException;
|
import com.baeldung.GetRequestMockServer;
|
||||||
|
import com.baeldung.httpclient.ResponseUtil;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* NOTE : Need module spring-security-rest-basic-auth to be running
|
* NOTE : Need module spring-security-rest-basic-auth to be running
|
||||||
*/
|
*/
|
||||||
public class HttpClientSandboxLiveTest extends GetRequestMockServer {
|
class HttpClientSandboxLiveTest extends GetRequestMockServer {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public final void givenGetRequestExecuted_whenAnalyzingTheResponse_thenCorrectStatusCode() throws IOException {
|
final void givenGetRequestExecuted_whenAnalyzingTheResponse_thenCorrectStatusCode() throws IOException {
|
||||||
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
|
||||||
final AuthScope authscp = new AuthScope("localhost", 8080);
|
final AuthScope authscp = new AuthScope("localhost", 8080);
|
||||||
credentialsProvider.setCredentials(authscp, new UsernamePasswordCredentials("user1", "user1Pass"));
|
credentialsProvider.setCredentials(authscp, new UsernamePasswordCredentials("user1", "user1Pass"));
|
|
@ -35,7 +35,7 @@ import org.springframework.web.client.RestTemplate;
|
||||||
* This test requires a localhost server over HTTPS <br>
|
* This test requires a localhost server over HTTPS <br>
|
||||||
* It should only be manually run, not part of the automated build
|
* It should only be manually run, not part of the automated build
|
||||||
* */
|
* */
|
||||||
public class RestClientV4LiveManualTest {
|
class RestClientV4LiveManualTest {
|
||||||
|
|
||||||
final String urlOverHttps = "http://localhost:8082/httpclient-simple/api/bars/1";
|
final String urlOverHttps = "http://localhost:8082/httpclient-simple/api/bars/1";
|
||||||
|
|
||||||
|
@ -81,7 +81,7 @@ public class RestClientV4LiveManualTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void whenHttpsUrlIsConsumed_thenException() throws ClientProtocolException, IOException {
|
void whenHttpsUrlIsConsumed_thenException() throws ClientProtocolException, IOException {
|
||||||
CloseableHttpClient httpClient = HttpClients.createDefault();
|
CloseableHttpClient httpClient = HttpClients.createDefault();
|
||||||
String urlOverHttps = "https://localhost:8082/httpclient-simple";
|
String urlOverHttps = "https://localhost:8082/httpclient-simple";
|
||||||
HttpGet getMethod = new HttpGet(urlOverHttps);
|
HttpGet getMethod = new HttpGet(urlOverHttps);
|
||||||
|
|
|
@ -2,8 +2,6 @@ package com.baeldung.httpclient;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.apache.http.HttpEntity;
|
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
|
||||||
public final class ClientUtil {
|
public final class ClientUtil {
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
package com.baeldung.httpclient;
|
package com.baeldung.httpclient;
|
||||||
|
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
|
||||||
|
|
|
@ -9,11 +9,11 @@ import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
import org.apache.http.impl.client.HttpClientBuilder;
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
import org.apache.http.impl.client.HttpClients;
|
import org.apache.http.impl.client.HttpClients;
|
||||||
|
|
||||||
import org.junit.After;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.Before;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
public class HttpClientCancelRequestV4LiveTest {
|
class HttpClientCancelRequestV4LiveTest {
|
||||||
|
|
||||||
private static final String SAMPLE_URL = "http://www.github.com";
|
private static final String SAMPLE_URL = "http://www.github.com";
|
||||||
|
|
||||||
|
@ -21,18 +21,18 @@ public class HttpClientCancelRequestV4LiveTest {
|
||||||
|
|
||||||
private CloseableHttpResponse response;
|
private CloseableHttpResponse response;
|
||||||
|
|
||||||
@Before
|
@BeforeEach
|
||||||
public final void before() {
|
public final void before() {
|
||||||
instance = HttpClientBuilder.create().build();
|
instance = HttpClientBuilder.create().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@After
|
@AfterEach
|
||||||
public final void after() throws IllegalStateException, IOException {
|
public final void after() throws IllegalStateException, IOException {
|
||||||
ResponseUtil.closeResponse(response);
|
ResponseUtil.closeResponse(response);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public final void whenRequestIsCanceled_thenCorrect() throws IOException {
|
final void whenRequestIsCanceled_thenCorrect() throws IOException {
|
||||||
instance = HttpClients.custom().build();
|
instance = HttpClients.custom().build();
|
||||||
final HttpGet request = new HttpGet(SAMPLE_URL);
|
final HttpGet request = new HttpGet(SAMPLE_URL);
|
||||||
response = instance.execute(request);
|
response = instance.execute(request);
|
||||||
|
|
|
@ -1,5 +1,9 @@
|
||||||
package com.baeldung.httpclient;
|
package com.baeldung.httpclient;
|
||||||
|
|
||||||
|
import org.apache.http.auth.AuthenticationException;
|
||||||
|
import org.apache.http.auth.UsernamePasswordCredentials;
|
||||||
|
import org.apache.http.entity.StringEntity;
|
||||||
|
import org.apache.http.impl.auth.BasicScheme;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
@ -181,4 +185,20 @@ class HttpClientCookBookV4LiveTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
final void whenExecutingPostRequestWithBody_thenNoExceptions() throws IOException {
|
||||||
|
final HttpPost request = new HttpPost(SAMPLE_POST_URL);
|
||||||
|
request.setEntity(new StringEntity("in the body of the POST"));
|
||||||
|
client.execute(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
final void givenAuth_whenExecutingPostRequestWithBody_thenNoExceptions() throws IOException, AuthenticationException {
|
||||||
|
final HttpPost request = new HttpPost(SAMPLE_POST_URL);
|
||||||
|
request.setEntity(new StringEntity("in the body of the POST"));
|
||||||
|
final UsernamePasswordCredentials creds = new UsernamePasswordCredentials("username", "password");
|
||||||
|
request.addHeader(new BasicScheme().authenticate(creds, request, null));
|
||||||
|
client.execute(request);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
package com.baeldung.httpclient;
|
package com.baeldung.httpclient;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
|
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import static org.hamcrest.MatcherAssert.assertThat;
|
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.apache.http.client.methods.CloseableHttpResponse;
|
import org.apache.http.client.methods.CloseableHttpResponse;
|
||||||
|
|
|
@ -92,6 +92,26 @@ class HttpClientTimeoutV4LiveTest extends GetRequestMockServer {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
final void givenLowTimeout_whenExecutingRequestWithTimeout_thenException() {
|
||||||
|
final RequestConfig requestConfig = RequestConfig.custom()
|
||||||
|
.setConnectionRequestTimeout(5)
|
||||||
|
.setConnectTimeout(5)
|
||||||
|
.setSocketTimeout(2)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
final CloseableHttpClient client = HttpClientBuilder.create()
|
||||||
|
.setDefaultRequestConfig(requestConfig)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
final HttpGet request = new HttpGet("http://www.github.com");
|
||||||
|
|
||||||
|
assertThrows(ConnectTimeoutException.class, () -> {
|
||||||
|
response = client.execute(request);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void whenSecuredRestApiIsConsumed_then200OK() throws IOException {
|
void whenSecuredRestApiIsConsumed_then200OK() throws IOException {
|
||||||
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
|
CloseableHttpClient httpClient = HttpClientBuilder.create().build();
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
package com.baeldung.httpclient.advancedconfig;
|
package com.baeldung.httpclient.advancedconfig;
|
||||||
|
|
||||||
|
import com.github.tomakehurst.wiremock.WireMockServer;
|
||||||
|
|
||||||
import com.github.tomakehurst.wiremock.junit.WireMockRule;
|
|
||||||
import org.apache.http.HttpHeaders;
|
import org.apache.http.HttpHeaders;
|
||||||
import org.apache.http.HttpHost;
|
import org.apache.http.HttpHost;
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
|
@ -19,8 +19,10 @@ import org.apache.http.impl.client.BasicAuthCache;
|
||||||
import org.apache.http.impl.client.BasicCredentialsProvider;
|
import org.apache.http.impl.client.BasicCredentialsProvider;
|
||||||
import org.apache.http.impl.client.HttpClients;
|
import org.apache.http.impl.client.HttpClients;
|
||||||
import org.apache.http.impl.conn.DefaultProxyRoutePlanner;
|
import org.apache.http.impl.conn.DefaultProxyRoutePlanner;
|
||||||
import org.junit.Rule;
|
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
|
@ -32,18 +34,29 @@ import static com.github.tomakehurst.wiremock.client.WireMock.getRequestedFor;
|
||||||
import static com.github.tomakehurst.wiremock.client.WireMock.post;
|
import static com.github.tomakehurst.wiremock.client.WireMock.post;
|
||||||
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
|
import static com.github.tomakehurst.wiremock.client.WireMock.urlEqualTo;
|
||||||
import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching;
|
import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching;
|
||||||
import static org.junit.Assert.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
public class HttpClientAdvancedConfigurationIntegrationTest {
|
class HttpClientAdvancedConfigurationIntegrationTest {
|
||||||
|
|
||||||
@Rule
|
public WireMockServer serviceMock;
|
||||||
public WireMockRule serviceMock = new WireMockRule(8089);
|
public WireMockServer proxyMock;
|
||||||
|
|
||||||
@Rule
|
@BeforeEach
|
||||||
public WireMockRule proxyMock = new WireMockRule(8090);
|
public void before () {
|
||||||
|
serviceMock = new WireMockServer(8089);
|
||||||
|
serviceMock.start();
|
||||||
|
proxyMock = new WireMockServer(8090);
|
||||||
|
proxyMock.start();
|
||||||
|
}
|
||||||
|
|
||||||
|
@AfterEach
|
||||||
|
public void after () {
|
||||||
|
serviceMock.stop();
|
||||||
|
proxyMock.stop();
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenClientWithCustomUserAgentHeader_whenExecuteRequest_shouldReturn200() throws IOException {
|
void givenClientWithCustomUserAgentHeader_whenExecuteRequest_shouldReturn200() throws IOException {
|
||||||
//given
|
//given
|
||||||
String userAgent = "BaeldungAgent/1.0";
|
String userAgent = "BaeldungAgent/1.0";
|
||||||
serviceMock.stubFor(get(urlEqualTo("/detail"))
|
serviceMock.stubFor(get(urlEqualTo("/detail"))
|
||||||
|
@ -59,11 +72,11 @@ public class HttpClientAdvancedConfigurationIntegrationTest {
|
||||||
HttpResponse response = httpClient.execute(httpGet);
|
HttpResponse response = httpClient.execute(httpGet);
|
||||||
|
|
||||||
//then
|
//then
|
||||||
assertEquals(response.getStatusLine().getStatusCode(), 200);
|
assertEquals(200, response.getStatusLine().getStatusCode());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenClientThatSendDataInBody_whenSendXmlInBody_shouldReturn200() throws IOException {
|
void givenClientThatSendDataInBody_whenSendXmlInBody_shouldReturn200() throws IOException {
|
||||||
//given
|
//given
|
||||||
String xmlBody = "<xml><id>1</id></xml>";
|
String xmlBody = "<xml><id>1</id></xml>";
|
||||||
serviceMock.stubFor(post(urlEqualTo("/person"))
|
serviceMock.stubFor(post(urlEqualTo("/person"))
|
||||||
|
@ -82,12 +95,11 @@ public class HttpClientAdvancedConfigurationIntegrationTest {
|
||||||
HttpResponse response = httpClient.execute(httpPost);
|
HttpResponse response = httpClient.execute(httpPost);
|
||||||
|
|
||||||
//then
|
//then
|
||||||
assertEquals(response.getStatusLine().getStatusCode(), 200);
|
assertEquals(200, response.getStatusLine().getStatusCode());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenServerThatIsBehindProxy_whenClientIsConfiguredToSendRequestViaProxy_shouldReturn200() throws IOException {
|
void givenServerThatIsBehindProxy_whenClientIsConfiguredToSendRequestViaProxy_shouldReturn200() throws IOException {
|
||||||
//given
|
//given
|
||||||
proxyMock.stubFor(get(urlMatching(".*"))
|
proxyMock.stubFor(get(urlMatching(".*"))
|
||||||
.willReturn(aResponse().proxiedFrom("http://localhost:8089/")));
|
.willReturn(aResponse().proxiedFrom("http://localhost:8089/")));
|
||||||
|
@ -107,13 +119,13 @@ public class HttpClientAdvancedConfigurationIntegrationTest {
|
||||||
HttpResponse response = httpclient.execute(httpGet);
|
HttpResponse response = httpclient.execute(httpGet);
|
||||||
|
|
||||||
//then
|
//then
|
||||||
assertEquals(response.getStatusLine().getStatusCode(), 200);
|
assertEquals(200, response.getStatusLine().getStatusCode());
|
||||||
proxyMock.verify(getRequestedFor(urlEqualTo("/private")));
|
proxyMock.verify(getRequestedFor(urlEqualTo("/private")));
|
||||||
serviceMock.verify(getRequestedFor(urlEqualTo("/private")));
|
serviceMock.verify(getRequestedFor(urlEqualTo("/private")));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenServerThatIsBehindAuthorizationProxy_whenClientSendRequest_shouldAuthorizeProperly() throws IOException {
|
void givenServerThatIsBehindAuthorizationProxy_whenClientSendRequest_shouldAuthorizeProperly() throws IOException {
|
||||||
//given
|
//given
|
||||||
proxyMock.stubFor(get(urlMatching("/private"))
|
proxyMock.stubFor(get(urlMatching("/private"))
|
||||||
.willReturn(aResponse().proxiedFrom("http://localhost:8089/")));
|
.willReturn(aResponse().proxiedFrom("http://localhost:8089/")));
|
||||||
|
@ -152,7 +164,7 @@ public class HttpClientAdvancedConfigurationIntegrationTest {
|
||||||
HttpResponse response = httpclient.execute(httpGet, context);
|
HttpResponse response = httpclient.execute(httpGet, context);
|
||||||
|
|
||||||
//then
|
//then
|
||||||
assertEquals(response.getStatusLine().getStatusCode(), 200);
|
assertEquals(200, response.getStatusLine().getStatusCode());
|
||||||
proxyMock.verify(getRequestedFor(urlEqualTo("/private")).withHeader("Authorization", containing("Basic")));
|
proxyMock.verify(getRequestedFor(urlEqualTo("/private")).withHeader("Authorization", containing("Basic")));
|
||||||
serviceMock.verify(getRequestedFor(urlEqualTo("/private")));
|
serviceMock.verify(getRequestedFor(urlEqualTo("/private")));
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,34 +12,35 @@ import org.apache.http.client.methods.HttpHead;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
import org.apache.http.impl.client.HttpClientBuilder;
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
import org.apache.http.util.EntityUtils;
|
import org.apache.http.util.EntityUtils;
|
||||||
import org.junit.Before;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
import static org.hamcrest.Matchers.equalTo;
|
import static org.hamcrest.Matchers.equalTo;
|
||||||
import static org.junit.Assert.assertThat;
|
|
||||||
|
|
||||||
public class HttpClientExpandUrlLiveTest {
|
|
||||||
|
class HttpClientExpandUrlLiveTest {
|
||||||
|
|
||||||
private CloseableHttpClient client;
|
private CloseableHttpClient client;
|
||||||
|
|
||||||
@Before
|
@BeforeEach
|
||||||
public final void before() {
|
public final void beforeEach() {
|
||||||
client = HttpClientBuilder.create().disableRedirectHandling().build();
|
client = HttpClientBuilder.create().disableRedirectHandling().build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public final void givenShortenedOnce_whenUrlIsExpanded_thenCorrectResult() throws IOException {
|
final void givenShortenedOnce_whenUrlIsExpanded_thenCorrectResult() throws IOException {
|
||||||
final String expectedResult = "https://www.baeldung.com/rest-versioning";
|
final String expectedResult = "https://www.baeldung.com/rest-versioning";
|
||||||
final String actualResult = expandSingleLevel("http://bit.ly/3LScTri");
|
final String actualResult = expandSingleLevel("http://bit.ly/3LScTri");
|
||||||
assertThat(actualResult, equalTo(expectedResult));
|
assertThat(actualResult, equalTo(expectedResult));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public final void givenShortenedMultiple_whenUrlIsExpanded_thenCorrectResult() throws IOException {
|
final void givenShortenedMultiple_whenUrlIsExpanded_thenCorrectResult() throws IOException {
|
||||||
final String expectedResult = "https://www.baeldung.com/rest-versioning";
|
final String expectedResult = "https://www.baeldung.com/rest-versioning";
|
||||||
final String actualResult = expand("http://t.co/e4rDDbnzmk");
|
final String actualResult = expand("http://t.co/e4rDDbnzmk");
|
||||||
assertThat(actualResult, equalTo(expectedResult));
|
assertThat(actualResult, equalTo(expectedResult));
|
||||||
|
|
|
@ -17,7 +17,6 @@ import com.baeldung.GetRequestMockServer;
|
||||||
|
|
||||||
class ApacheHttpClientUnitTest extends GetRequestMockServer {
|
class ApacheHttpClientUnitTest extends GetRequestMockServer {
|
||||||
|
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void givenDeveloperUsedCloseableHttpResponse_whenExecutingGetRequest_thenStatusIsOk() throws IOException {
|
void givenDeveloperUsedCloseableHttpResponse_whenExecutingGetRequest_thenStatusIsOk() throws IOException {
|
||||||
try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {
|
try (CloseableHttpClient httpClient = HttpClientBuilder.create().build()) {
|
||||||
|
|
|
@ -1,7 +1,9 @@
|
||||||
package com.baeldung.httpclient.httpclient.conn;
|
package com.baeldung.httpclient.httpclient.conn;
|
||||||
|
|
||||||
import static org.junit.Assert.assertTrue;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
@ -24,6 +26,7 @@ import org.apache.http.conn.ConnectionPoolTimeoutException;
|
||||||
import org.apache.http.conn.ConnectionRequest;
|
import org.apache.http.conn.ConnectionRequest;
|
||||||
import org.apache.http.conn.routing.HttpRoute;
|
import org.apache.http.conn.routing.HttpRoute;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
|
import org.apache.http.impl.client.HttpClientBuilder;
|
||||||
import org.apache.http.impl.client.HttpClients;
|
import org.apache.http.impl.client.HttpClients;
|
||||||
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
|
import org.apache.http.impl.conn.BasicHttpClientConnectionManager;
|
||||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||||
|
@ -33,14 +36,14 @@ import org.apache.http.protocol.HttpContext;
|
||||||
import org.apache.http.protocol.HttpCoreContext;
|
import org.apache.http.protocol.HttpCoreContext;
|
||||||
import org.apache.http.protocol.HttpRequestExecutor;
|
import org.apache.http.protocol.HttpRequestExecutor;
|
||||||
import org.apache.http.util.EntityUtils;
|
import org.apache.http.util.EntityUtils;
|
||||||
import org.junit.Ignore;
|
import org.junit.jupiter.api.Disabled;
|
||||||
import org.junit.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
public class HttpClientConnectionManagementLiveTest {
|
class HttpClientConnectionManagementLiveTest {
|
||||||
|
|
||||||
// Example 2.1. Getting a Connection Request for a Low Level Connection (HttpClientConnection)
|
// Example 2.1. Getting a Connection Request for a Low Level Connection (HttpClientConnection)
|
||||||
@Test
|
@Test
|
||||||
public final void whenLowLevelConnectionIsEstablished_thenNoExceptions() throws ConnectionPoolTimeoutException, InterruptedException, ExecutionException {
|
final void whenLowLevelConnectionIsEstablished_thenNoExceptions() throws ConnectionPoolTimeoutException, InterruptedException, ExecutionException {
|
||||||
try (BasicHttpClientConnectionManager connManager = new BasicHttpClientConnectionManager()) {
|
try (BasicHttpClientConnectionManager connManager = new BasicHttpClientConnectionManager()) {
|
||||||
HttpRoute route = new HttpRoute(new HttpHost("www.baeldung.com", 80));
|
HttpRoute route = new HttpRoute(new HttpHost("www.baeldung.com", 80));
|
||||||
final ConnectionRequest connRequest = connManager.requestConnection(route, null);
|
final ConnectionRequest connRequest = connManager.requestConnection(route, null);
|
||||||
|
@ -50,20 +53,20 @@ public class HttpClientConnectionManagementLiveTest {
|
||||||
|
|
||||||
// Example 3.1. Setting the PoolingHttpClientConnectionManager on a HttpClient
|
// Example 3.1. Setting the PoolingHttpClientConnectionManager on a HttpClient
|
||||||
@Test
|
@Test
|
||||||
public final void whenPollingConnectionManagerIsConfiguredOnHttpClient_thenNoExceptions() throws ClientProtocolException, IOException {
|
final void whenPollingConnectionManagerIsConfiguredOnHttpClient_thenNoExceptions() throws ClientProtocolException, IOException {
|
||||||
PoolingHttpClientConnectionManager poolingConnManager = new PoolingHttpClientConnectionManager();
|
PoolingHttpClientConnectionManager poolingConnManager = new PoolingHttpClientConnectionManager();
|
||||||
CloseableHttpClient client = HttpClients.custom()
|
CloseableHttpClient client = HttpClients.custom()
|
||||||
.setConnectionManager(poolingConnManager)
|
.setConnectionManager(poolingConnManager)
|
||||||
.build();
|
.build();
|
||||||
client.execute(new HttpGet("https://www.baeldung.com"));
|
client.execute(new HttpGet("https://www.baeldung.com"));
|
||||||
|
|
||||||
assertTrue(poolingConnManager.getTotalStats()
|
assertEquals(1, poolingConnManager.getTotalStats()
|
||||||
.getLeased() == 1);
|
.getLeased());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example 3.2. Using Two HttpClients to Connect to One Target Host Each
|
// Example 3.2. Using Two HttpClients to Connect to One Target Host Each
|
||||||
@Test
|
@Test
|
||||||
public final void whenTwoConnectionsForTwoRequests_thenNoExceptions() throws InterruptedException {
|
final void whenTwoConnectionsForTwoRequests_thenNoExceptions() throws InterruptedException {
|
||||||
HttpGet get1 = new HttpGet("https://www.baeldung.com");
|
HttpGet get1 = new HttpGet("https://www.baeldung.com");
|
||||||
HttpGet get2 = new HttpGet("https://www.google.com");
|
HttpGet get2 = new HttpGet("https://www.google.com");
|
||||||
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
|
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
|
||||||
|
@ -81,13 +84,13 @@ public class HttpClientConnectionManagementLiveTest {
|
||||||
thread1.join();
|
thread1.join();
|
||||||
thread2.join();
|
thread2.join();
|
||||||
|
|
||||||
assertTrue(connManager.getTotalStats()
|
assertEquals(0, connManager.getTotalStats()
|
||||||
.getLeased() == 0);
|
.getLeased());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example 4.1. Increasing the Number of Connections that Can be Open and Managed Beyond the default Limits
|
// Example 4.1. Increasing the Number of Connections that Can be Open and Managed Beyond the default Limits
|
||||||
@Test
|
@Test
|
||||||
public final void whenIncreasingConnectionPool_thenNoEceptions() {
|
final void whenIncreasingConnectionPool_thenNoEceptions() {
|
||||||
try (PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager()) {
|
try (PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager()) {
|
||||||
connManager.setMaxTotal(5);
|
connManager.setMaxTotal(5);
|
||||||
connManager.setDefaultMaxPerRoute(4);
|
connManager.setDefaultMaxPerRoute(4);
|
||||||
|
@ -98,7 +101,7 @@ public class HttpClientConnectionManagementLiveTest {
|
||||||
|
|
||||||
// Example 4.2. Using Threads to Execute Connections
|
// Example 4.2. Using Threads to Execute Connections
|
||||||
@Test
|
@Test
|
||||||
public final void whenExecutingSameRequestsInDifferentThreads_thenExecuteReuqest() throws InterruptedException {
|
final void whenExecutingSameRequestsInDifferentThreads_thenExecuteReuqest() throws InterruptedException {
|
||||||
HttpGet get = new HttpGet("http://www.baeldung.com");
|
HttpGet get = new HttpGet("http://www.baeldung.com");
|
||||||
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
|
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
|
||||||
CloseableHttpClient client = HttpClients.custom()
|
CloseableHttpClient client = HttpClients.custom()
|
||||||
|
@ -117,7 +120,7 @@ public class HttpClientConnectionManagementLiveTest {
|
||||||
|
|
||||||
// Example 5.1. A Custom Keep Alive Strategy
|
// Example 5.1. A Custom Keep Alive Strategy
|
||||||
@Test
|
@Test
|
||||||
public final void whenCustomizingKeepAliveStrategy_thenNoExceptions() {
|
final void whenCustomizingKeepAliveStrategy_thenNoExceptions() {
|
||||||
final ConnectionKeepAliveStrategy myStrategy = new ConnectionKeepAliveStrategy() {
|
final ConnectionKeepAliveStrategy myStrategy = new ConnectionKeepAliveStrategy() {
|
||||||
@Override
|
@Override
|
||||||
public long getKeepAliveDuration(final HttpResponse myResponse, final HttpContext myContext) {
|
public long getKeepAliveDuration(final HttpResponse myResponse, final HttpContext myContext) {
|
||||||
|
@ -148,7 +151,7 @@ public class HttpClientConnectionManagementLiveTest {
|
||||||
|
|
||||||
// Example 6.1. BasicHttpClientConnectionManager Connection Reuse
|
// Example 6.1. BasicHttpClientConnectionManager Connection Reuse
|
||||||
@Test
|
@Test
|
||||||
public final void givenBasicHttpClientConnManager_whenConnectionReuse_thenNoExceptions() throws IOException, HttpException, InterruptedException, ExecutionException {
|
final void givenBasicHttpClientConnManager_whenConnectionReuse_thenNoExceptions() throws IOException, HttpException, InterruptedException, ExecutionException {
|
||||||
BasicHttpClientConnectionManager basicConnManager = new BasicHttpClientConnectionManager();
|
BasicHttpClientConnectionManager basicConnManager = new BasicHttpClientConnectionManager();
|
||||||
HttpClientContext context = HttpClientContext.create();
|
HttpClientContext context = HttpClientContext.create();
|
||||||
|
|
||||||
|
@ -175,7 +178,7 @@ public class HttpClientConnectionManagementLiveTest {
|
||||||
|
|
||||||
// Example 6.2. PoolingHttpClientConnectionManager: Re-Using Connections with Threads
|
// Example 6.2. PoolingHttpClientConnectionManager: Re-Using Connections with Threads
|
||||||
@Test
|
@Test
|
||||||
public final void whenConnectionsNeededGreaterThanMaxTotal_thenLeaseMasTotalandReuse() throws InterruptedException {
|
final void whenConnectionsNeededGreaterThanMaxTotal_thenLeaseMasTotalandReuse() throws InterruptedException {
|
||||||
HttpGet get = new HttpGet("http://echo.200please.com");
|
HttpGet get = new HttpGet("http://echo.200please.com");
|
||||||
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
|
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
|
||||||
connManager.setDefaultMaxPerRoute(5);
|
connManager.setDefaultMaxPerRoute(5);
|
||||||
|
@ -197,20 +200,20 @@ public class HttpClientConnectionManagementLiveTest {
|
||||||
|
|
||||||
// Example 7.1. Setting Socket Timeout to 5 Seconds
|
// Example 7.1. Setting Socket Timeout to 5 Seconds
|
||||||
@Test
|
@Test
|
||||||
public final void whenConfiguringTimeOut_thenNoExceptions() {
|
final void whenConfiguringTimeOut_thenNoExceptions() {
|
||||||
HttpRoute route = new HttpRoute(new HttpHost("www.baeldung.com", 80));
|
HttpRoute route = new HttpRoute(new HttpHost("www.baeldung.com", 80));
|
||||||
try (PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager()) {
|
try (PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager()) {
|
||||||
connManager.setSocketConfig(route.getTargetHost(), SocketConfig.custom()
|
connManager.setSocketConfig(route.getTargetHost(), SocketConfig.custom()
|
||||||
.setSoTimeout(5000)
|
.setSoTimeout(5000)
|
||||||
.build());
|
.build());
|
||||||
assertTrue(connManager.getSocketConfig(route.getTargetHost())
|
assertEquals(5000, connManager.getSocketConfig(route.getTargetHost())
|
||||||
.getSoTimeout() == 5000);
|
.getSoTimeout());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example 8.1. Setting the HttpClient to Check for Stale Connections
|
// Example 8.1. Setting the HttpClient to Check for Stale Connections
|
||||||
@Test
|
@Test
|
||||||
public final void whenHttpClientChecksStaleConns_thenNoExceptions() {
|
final void whenHttpClientChecksStaleConns_thenNoExceptions() {
|
||||||
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
|
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
|
||||||
HttpClients.custom()
|
HttpClients.custom()
|
||||||
.setDefaultRequestConfig(RequestConfig.custom()
|
.setDefaultRequestConfig(RequestConfig.custom()
|
||||||
|
@ -222,7 +225,7 @@ public class HttpClientConnectionManagementLiveTest {
|
||||||
|
|
||||||
// Example 8.2. Using a Stale Connection Monitor Thread
|
// Example 8.2. Using a Stale Connection Monitor Thread
|
||||||
@Test
|
@Test
|
||||||
public final void whenCustomizedIdleConnMonitor_thenNoExceptions() throws InterruptedException {
|
final void whenCustomizedIdleConnMonitor_thenNoExceptions() throws InterruptedException {
|
||||||
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
|
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
|
||||||
HttpClients.custom()
|
HttpClients.custom()
|
||||||
.setConnectionManager(connManager)
|
.setConnectionManager(connManager)
|
||||||
|
@ -233,8 +236,8 @@ public class HttpClientConnectionManagementLiveTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Example 9.1. Closing Connection and Releasing Resources
|
// Example 9.1. Closing Connection and Releasing Resources
|
||||||
@Test(expected = IllegalStateException.class)
|
@Test
|
||||||
public final void whenClosingConnectionsandManager_thenCloseWithNoExceptions1() throws InterruptedException, ExecutionException, IOException, HttpException {
|
final void whenClosingConnectionsAndManager_thenCloseWithNoExceptions1() throws IOException {
|
||||||
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
|
PoolingHttpClientConnectionManager connManager = new PoolingHttpClientConnectionManager();
|
||||||
CloseableHttpClient client = HttpClients.custom()
|
CloseableHttpClient client = HttpClients.custom()
|
||||||
.setConnectionManager(connManager)
|
.setConnectionManager(connManager)
|
||||||
|
@ -248,14 +251,14 @@ public class HttpClientConnectionManagementLiveTest {
|
||||||
connManager.close();
|
connManager.close();
|
||||||
connManager.shutdown();
|
connManager.shutdown();
|
||||||
|
|
||||||
client.execute(get);
|
assertThrows(IllegalStateException.class, () -> {
|
||||||
|
client.execute(get);
|
||||||
assertTrue(response.getEntity() == null);
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
// Example 3.2. TESTER VERSION
|
// Example 3.2. TESTER VERSION
|
||||||
public final void whenTwoConnectionsForTwoRequests_thenTwoConnectionsAreLeased() throws InterruptedException {
|
final void whenTwoConnectionsForTwoRequests_thenTwoConnectionsAreLeased() throws InterruptedException {
|
||||||
HttpGet get1 = new HttpGet("https://www.baeldung.com");
|
HttpGet get1 = new HttpGet("https://www.baeldung.com");
|
||||||
HttpGet get2 = new HttpGet("https://www.google.com");
|
HttpGet get2 = new HttpGet("https://www.google.com");
|
||||||
|
|
||||||
|
@ -273,13 +276,13 @@ public class HttpClientConnectionManagementLiveTest {
|
||||||
thread2.start();
|
thread2.start();
|
||||||
thread1.join();
|
thread1.join();
|
||||||
thread2.join(1000);
|
thread2.join(1000);
|
||||||
assertTrue(poolingConnManager.getTotalStats()
|
assertEquals(2, poolingConnManager.getTotalStats()
|
||||||
.getLeased() == 2);
|
.getLeased());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
// Example 4.2 Tester Version
|
// Example 4.2 Tester Version
|
||||||
public final void whenExecutingSameRequestsInDifferentThreads_thenUseDefaultConnLimit() throws InterruptedException {
|
final void whenExecutingSameRequestsInDifferentThreads_thenUseDefaultConnLimit() throws InterruptedException {
|
||||||
PoolingHttpClientConnectionManager poolingConnManager = new PoolingHttpClientConnectionManager();
|
PoolingHttpClientConnectionManager poolingConnManager = new PoolingHttpClientConnectionManager();
|
||||||
CloseableHttpClient client = HttpClients.custom()
|
CloseableHttpClient client = HttpClients.custom()
|
||||||
.setConnectionManager(poolingConnManager)
|
.setConnectionManager(poolingConnManager)
|
||||||
|
@ -297,7 +300,7 @@ public class HttpClientConnectionManagementLiveTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
// 6.2 TESTER VERSION
|
// 6.2 TESTER VERSION
|
||||||
public final void whenConnectionsNeededGreaterThanMaxTotal_thenReuseConnections() throws InterruptedException {
|
final void whenConnectionsNeededGreaterThanMaxTotal_thenReuseConnections() throws InterruptedException {
|
||||||
PoolingHttpClientConnectionManager poolingConnManager = new PoolingHttpClientConnectionManager();
|
PoolingHttpClientConnectionManager poolingConnManager = new PoolingHttpClientConnectionManager();
|
||||||
poolingConnManager.setDefaultMaxPerRoute(5);
|
poolingConnManager.setDefaultMaxPerRoute(5);
|
||||||
poolingConnManager.setMaxTotal(5);
|
poolingConnManager.setMaxTotal(5);
|
||||||
|
@ -316,15 +319,15 @@ public class HttpClientConnectionManagementLiveTest {
|
||||||
thread.join(10000);
|
thread.join(10000);
|
||||||
countConnMade++;
|
countConnMade++;
|
||||||
if (countConnMade == 0) {
|
if (countConnMade == 0) {
|
||||||
assertTrue(thread.getLeasedConn() == 5);
|
assertEquals(5, thread.getLeasedConn());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
@Ignore("Very Long Running")
|
@Disabled("Very Long Running")
|
||||||
// 8.2 TESTER VERSION
|
// 8.2 TESTER VERSION
|
||||||
public final void whenCustomizedIdleConnMonitor_thenEliminateIdleConns() throws InterruptedException {
|
final void whenCustomizedIdleConnMonitor_thenEliminateIdleConns() throws InterruptedException {
|
||||||
PoolingHttpClientConnectionManager poolingConnManager = new PoolingHttpClientConnectionManager();
|
PoolingHttpClientConnectionManager poolingConnManager = new PoolingHttpClientConnectionManager();
|
||||||
CloseableHttpClient client = HttpClients.custom()
|
CloseableHttpClient client = HttpClients.custom()
|
||||||
.setConnectionManager(poolingConnManager)
|
.setConnectionManager(poolingConnManager)
|
||||||
|
@ -340,10 +343,10 @@ public class HttpClientConnectionManagementLiveTest {
|
||||||
thread2.start();
|
thread2.start();
|
||||||
thread2.join();
|
thread2.join();
|
||||||
thread3.start();
|
thread3.start();
|
||||||
assertTrue(poolingConnManager.getTotalStats()
|
assertEquals(1, poolingConnManager.getTotalStats()
|
||||||
.getAvailable() == 1);
|
.getAvailable());
|
||||||
thread3.join(32000);
|
thread3.join(32000);
|
||||||
assertTrue(poolingConnManager.getTotalStats()
|
assertEquals(0, poolingConnManager.getTotalStats()
|
||||||
.getAvailable() == 0);
|
.getAvailable());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,7 +3,6 @@ package com.baeldung.httpclient.httpclient.conn;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
import org.apache.http.client.ClientProtocolException;
|
|
||||||
import org.apache.http.client.methods.HttpGet;
|
import org.apache.http.client.methods.HttpGet;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||||
|
|
|
@ -2,7 +2,6 @@ package com.baeldung.httpclient.httpclient.conn;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
import org.apache.http.client.ClientProtocolException;
|
|
||||||
import org.apache.http.client.methods.HttpGet;
|
import org.apache.http.client.methods.HttpGet;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
|
||||||
|
|
|
@ -6,18 +6,19 @@ import org.apache.http.client.methods.HttpGet;
|
||||||
import org.apache.http.impl.client.CloseableHttpClient;
|
import org.apache.http.impl.client.CloseableHttpClient;
|
||||||
import org.apache.http.impl.client.HttpClients;
|
import org.apache.http.impl.client.HttpClients;
|
||||||
import org.apache.http.util.EntityUtils;
|
import org.apache.http.util.EntityUtils;
|
||||||
import org.junit.Test;
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
|
||||||
public class ApacheHttpClientUnitTest {
|
class ApacheHttpClientUnitTest {
|
||||||
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
private final Logger logger = LoggerFactory.getLogger(this.getClass());
|
||||||
public static final String DUMMY_URL = "https://postman-echo.com/get";
|
public static final String DUMMY_URL = "https://postman-echo.com/get";
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void whenUseApacheHttpClient_thenCorrect() throws IOException {
|
void whenUseApacheHttpClient_thenCorrect() throws IOException {
|
||||||
HttpGet request = new HttpGet(DUMMY_URL);
|
HttpGet request = new HttpGet(DUMMY_URL);
|
||||||
|
|
||||||
try (CloseableHttpClient client = HttpClients.createDefault(); CloseableHttpResponse response = client.execute(request)) {
|
try (CloseableHttpClient client = HttpClients.createDefault(); CloseableHttpResponse response = client.execute(request)) {
|
||||||
|
|
|
@ -24,7 +24,7 @@ import org.junit.jupiter.api.AfterEach;
|
||||||
import org.junit.jupiter.api.BeforeEach;
|
import org.junit.jupiter.api.BeforeEach;
|
||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
public class ApacheHttpClientRetryLiveTest {
|
class ApacheHttpClientRetryLiveTest {
|
||||||
|
|
||||||
private Integer requestCounter;
|
private Integer requestCounter;
|
||||||
private CloseableHttpClient httpClient;
|
private CloseableHttpClient httpClient;
|
||||||
|
@ -93,14 +93,14 @@ public class ApacheHttpClientRetryLiveTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenDefaultConfiguration_whenReceivedIOException_thenRetriesPerformed() {
|
void givenDefaultConfiguration_whenReceivedIOException_thenRetriesPerformed() {
|
||||||
createFailingHttpClient();
|
createFailingHttpClient();
|
||||||
assertThrows(IOException.class, () -> httpClient.execute(new HttpGet("https://httpstat.us/200")));
|
assertThrows(IOException.class, () -> httpClient.execute(new HttpGet("https://httpstat.us/200")));
|
||||||
assertThat(requestCounter).isEqualTo(4);
|
assertThat(requestCounter).isEqualTo(4);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenDefaultConfiguration_whenDomainNameNotResolved_thenNoRetryApplied() {
|
void givenDefaultConfiguration_whenDomainNameNotResolved_thenNoRetryApplied() {
|
||||||
createDefaultApacheHttpClient();
|
createDefaultApacheHttpClient();
|
||||||
HttpGet request = new HttpGet(URI.create("http://domain.that.does.not.exist:80/api/v1"));
|
HttpGet request = new HttpGet(URI.create("http://domain.that.does.not.exist:80/api/v1"));
|
||||||
|
|
||||||
|
@ -109,7 +109,7 @@ public class ApacheHttpClientRetryLiveTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenDefaultConfiguration_whenGotInternalServerError_thenNoRetryLogicApplied() throws IOException {
|
void givenDefaultConfiguration_whenGotInternalServerError_thenNoRetryLogicApplied() throws IOException {
|
||||||
createDefaultApacheHttpClient();
|
createDefaultApacheHttpClient();
|
||||||
HttpGet request = new HttpGet(URI.create("https://httpstat.us/500"));
|
HttpGet request = new HttpGet(URI.create("https://httpstat.us/500"));
|
||||||
|
|
||||||
|
@ -120,7 +120,7 @@ public class ApacheHttpClientRetryLiveTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenDefaultConfiguration_whenHttpPatchRequest_thenRetryIsNotApplied() {
|
void givenDefaultConfiguration_whenHttpPatchRequest_thenRetryIsNotApplied() {
|
||||||
createFailingHttpClient();
|
createFailingHttpClient();
|
||||||
HttpPatch request = new HttpPatch(URI.create("https://httpstat.us/500"));
|
HttpPatch request = new HttpPatch(URI.create("https://httpstat.us/500"));
|
||||||
|
|
||||||
|
@ -129,7 +129,7 @@ public class ApacheHttpClientRetryLiveTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenDefaultConfiguration_whenHttpPutRequest_thenRetryIsNotApplied() {
|
void givenDefaultConfiguration_whenHttpPutRequest_thenRetryIsNotApplied() {
|
||||||
createFailingHttpClient();
|
createFailingHttpClient();
|
||||||
HttpPut request = new HttpPut(URI.create("https://httpstat.us/500"));
|
HttpPut request = new HttpPut(URI.create("https://httpstat.us/500"));
|
||||||
|
|
||||||
|
@ -138,7 +138,7 @@ public class ApacheHttpClientRetryLiveTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenConfiguredRetryHandler_whenHttpPostRequest_thenRetriesPerformed() {
|
void givenConfiguredRetryHandler_whenHttpPostRequest_thenRetriesPerformed() {
|
||||||
createHttpClientWithRetryHandler();
|
createHttpClientWithRetryHandler();
|
||||||
|
|
||||||
HttpPost request = new HttpPost(URI.create("https://httpstat.us/200"));
|
HttpPost request = new HttpPost(URI.create("https://httpstat.us/200"));
|
||||||
|
@ -148,7 +148,7 @@ public class ApacheHttpClientRetryLiveTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenCustomRetryHandler_whenUnknownHostException_thenRetryAnyway() {
|
void givenCustomRetryHandler_whenUnknownHostException_thenRetryAnyway() {
|
||||||
createHttpClientWithCustomRetryHandler();
|
createHttpClientWithCustomRetryHandler();
|
||||||
|
|
||||||
HttpGet request = new HttpGet(URI.create("https://domain.that.does.not.exist/200"));
|
HttpGet request = new HttpGet(URI.create("https://domain.that.does.not.exist/200"));
|
||||||
|
@ -158,7 +158,7 @@ public class ApacheHttpClientRetryLiveTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenDisabledRetries_whenExecutedHttpRequestEndUpWithIOException_thenRetryIsNotApplied() {
|
void givenDisabledRetries_whenExecutedHttpRequestEndUpWithIOException_thenRetryIsNotApplied() {
|
||||||
createHttpClientWithRetriesDisabled();
|
createHttpClientWithRetriesDisabled();
|
||||||
HttpGet request = new HttpGet(URI.create("https://httpstat.us/200"));
|
HttpGet request = new HttpGet(URI.create("https://httpstat.us/200"));
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,2 @@
|
||||||
|
## Relevant Articles
|
||||||
|
- [Understanding XSLT Processing in Java](https://www.baeldung.com/java-extensible-stylesheet-language-transformations)
|
|
@ -21,7 +21,6 @@
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<javax.validation.validation-api.version>2.0.1.Final</javax.validation.validation-api.version>
|
<javax.validation.validation-api.version>2.0.1.Final</javax.validation.validation-api.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
|
@ -0,0 +1,31 @@
|
||||||
|
package com.baeldung.xsltProcessing;
|
||||||
|
|
||||||
|
import javax.xml.transform.*;
|
||||||
|
import javax.xml.transform.stream.StreamResult;
|
||||||
|
import javax.xml.transform.stream.StreamSource;
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public class XSLTProcessorWithParametersAndOption {
|
||||||
|
public static void transformXMLWithParametersAndOption(
|
||||||
|
String inputXMLPath,
|
||||||
|
String xsltPath,
|
||||||
|
String outputHTMLPath,
|
||||||
|
String companyName,
|
||||||
|
boolean enableIndentation
|
||||||
|
) throws TransformerException {
|
||||||
|
TransformerFactory transformerFactory = TransformerFactory.newInstance();
|
||||||
|
Source xsltSource = new StreamSource(new File(xsltPath));
|
||||||
|
Transformer transformer = transformerFactory.newTransformer(xsltSource);
|
||||||
|
|
||||||
|
transformer.setParameter("companyName", companyName);
|
||||||
|
|
||||||
|
if (enableIndentation) {
|
||||||
|
transformer.setOutputProperty(OutputKeys.INDENT, "yes");
|
||||||
|
}
|
||||||
|
|
||||||
|
Source xmlSource = new StreamSource(new File(inputXMLPath));
|
||||||
|
Result outputResult = new StreamResult(new File(outputHTMLPath));
|
||||||
|
|
||||||
|
transformer.transform(xmlSource, outputResult);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,21 @@
|
||||||
|
package com.baeldung.xsltProcessing;
|
||||||
|
|
||||||
|
import javax.xml.transform.*;
|
||||||
|
import javax.xml.transform.stream.StreamResult;
|
||||||
|
import javax.xml.transform.stream.StreamSource;
|
||||||
|
import java.io.File;
|
||||||
|
|
||||||
|
public class XSLTProcessorWithTemplate {
|
||||||
|
public static void transformXMLUsingTemplate(String inputXMLPath, String xsltPath, String outputHTMLPath) throws TransformerException {
|
||||||
|
TransformerFactory transformerFactory = TransformerFactory.newInstance();
|
||||||
|
Source xsltSource = new StreamSource(new File(xsltPath));
|
||||||
|
Templates templates = transformerFactory.newTemplates(xsltSource);
|
||||||
|
|
||||||
|
Transformer transformer = templates.newTransformer();
|
||||||
|
|
||||||
|
Source xmlSource = new StreamSource(new File(inputXMLPath));
|
||||||
|
Result outputResult = new StreamResult(new File(outputHTMLPath));
|
||||||
|
|
||||||
|
transformer.transform(xmlSource, outputResult);
|
||||||
|
}
|
||||||
|
}
|
|
@ -63,7 +63,6 @@
|
||||||
<org.apache.httpcomponents.version>4.5.2</org.apache.httpcomponents.version>
|
<org.apache.httpcomponents.version>4.5.2</org.apache.httpcomponents.version>
|
||||||
<velocity-version>1.7</velocity-version>
|
<velocity-version>1.7</velocity-version>
|
||||||
<velocity-tools-version>2.0</velocity-tools-version>
|
<velocity-tools-version>2.0</velocity-tools-version>
|
||||||
<maven-war-plugin.version>3.3.2</maven-war-plugin.version>
|
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
|
@ -49,7 +49,6 @@
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<asm.version>5.2</asm.version>
|
<asm.version>5.2</asm.version>
|
||||||
<maven-jar-plugin.version>2.4</maven-jar-plugin.version>
|
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
|
@ -1,6 +1,7 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>aws-s3-update-object</artifactId>
|
<artifactId>aws-s3-update-object</artifactId>
|
||||||
<version>0.0.1-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
|
|
@ -8,4 +8,6 @@ This module contains articles about Simple Storage Service (S3) on AWS
|
||||||
- [Multipart Uploads in Amazon S3 with Java](https://www.baeldung.com/aws-s3-multipart-upload)
|
- [Multipart Uploads in Amazon S3 with Java](https://www.baeldung.com/aws-s3-multipart-upload)
|
||||||
- [Using the JetS3t Java Client With Amazon S3](https://www.baeldung.com/jets3t-amazon-s3)
|
- [Using the JetS3t Java Client With Amazon S3](https://www.baeldung.com/jets3t-amazon-s3)
|
||||||
- [Check if a Specified Key Exists in a Given S3 Bucket Using Java](https://www.baeldung.com/java-aws-s3-check-specified-key-exists)
|
- [Check if a Specified Key Exists in a Given S3 Bucket Using Java](https://www.baeldung.com/java-aws-s3-check-specified-key-exists)
|
||||||
- [Listing All AWS S3 Objects in a Bucket Using Java](https://www.baeldung.com/java-aws-s3-list-bucket-objects)
|
- [Listing All AWS S3 Objects in a Bucket Using Java](https://www.baeldung.com/java-aws-s3-list-bucket-objects)
|
||||||
|
- [Update an Existing Amazon S3 Object Using Java](https://www.baeldung.com/java-update-amazon-s3-object)
|
||||||
|
- [How To Rename Files and Folders in Amazon S3](https://www.baeldung.com/java-amazon-s3-rename-files-folders)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>aws-s3</artifactId>
|
<artifactId>aws-s3</artifactId>
|
||||||
<version>0.1.0-SNAPSHOT</version>
|
<version>0.1.0-SNAPSHOT</version>
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
package com.baeldung.s3;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
import software.amazon.awssdk.auth.credentials.ProfileCredentialsProvider;
|
||||||
|
import software.amazon.awssdk.regions.Region;
|
||||||
|
import software.amazon.awssdk.services.s3.S3Client;
|
||||||
|
import software.amazon.awssdk.services.s3.model.CopyObjectRequest;
|
||||||
|
import software.amazon.awssdk.services.s3.model.DeleteObjectRequest;
|
||||||
|
import software.amazon.awssdk.services.s3.model.ListObjectsV2Request;
|
||||||
|
import software.amazon.awssdk.services.s3.model.ListObjectsV2Response;
|
||||||
|
import software.amazon.awssdk.services.s3.model.S3Object;
|
||||||
|
|
||||||
|
public class RenameObjectService {
|
||||||
|
|
||||||
|
private S3Client s3Client;
|
||||||
|
|
||||||
|
public RenameObjectService(S3Client s3Client) {
|
||||||
|
this.s3Client = s3Client;
|
||||||
|
}
|
||||||
|
|
||||||
|
public RenameObjectService() {
|
||||||
|
init();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void init() {
|
||||||
|
this.s3Client = S3Client.builder()
|
||||||
|
.region(Region.US_EAST_1)
|
||||||
|
.credentialsProvider(ProfileCredentialsProvider.create("default"))
|
||||||
|
.build();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void renameFile(String bucketName, String keyName, String destinationKeyName) {
|
||||||
|
CopyObjectRequest copyObjRequest = CopyObjectRequest.builder()
|
||||||
|
.sourceBucket(bucketName)
|
||||||
|
.sourceKey(keyName)
|
||||||
|
.destinationBucket(destinationKeyName)
|
||||||
|
.destinationKey(bucketName)
|
||||||
|
.build();
|
||||||
|
s3Client.copyObject(copyObjRequest);
|
||||||
|
DeleteObjectRequest deleteRequest = DeleteObjectRequest.builder()
|
||||||
|
.bucket(bucketName)
|
||||||
|
.key(keyName)
|
||||||
|
.build();
|
||||||
|
s3Client.deleteObject(deleteRequest);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void renameFolder(String bucketName, String sourceFolderKey, String destinationFolderKey) {
|
||||||
|
ListObjectsV2Request listRequest = ListObjectsV2Request.builder()
|
||||||
|
.bucket(bucketName)
|
||||||
|
.prefix(sourceFolderKey)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
ListObjectsV2Response listResponse = s3Client.listObjectsV2(listRequest);
|
||||||
|
List<S3Object> objects = listResponse.contents();
|
||||||
|
|
||||||
|
for (S3Object s3Object : objects) {
|
||||||
|
String newKey = destinationFolderKey + s3Object.key()
|
||||||
|
.substring(sourceFolderKey.length());
|
||||||
|
|
||||||
|
// Copy object to destination folder
|
||||||
|
CopyObjectRequest copyRequest = CopyObjectRequest.builder()
|
||||||
|
.sourceBucket(bucketName)
|
||||||
|
.sourceKey(s3Object.key())
|
||||||
|
.destinationBucket(bucketName)
|
||||||
|
.destinationKey(newKey)
|
||||||
|
.build();
|
||||||
|
s3Client.copyObject(copyRequest);
|
||||||
|
|
||||||
|
// Delete object from source folder
|
||||||
|
DeleteObjectRequest deleteRequest = DeleteObjectRequest.builder()
|
||||||
|
.bucket(bucketName)
|
||||||
|
.key(s3Object.key())
|
||||||
|
.build();
|
||||||
|
s3Client.deleteObject(deleteRequest);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -122,7 +122,6 @@
|
||||||
<docker.image.prefix>${azure.containerRegistry}.azurecr.io</docker.image.prefix>
|
<docker.image.prefix>${azure.containerRegistry}.azurecr.io</docker.image.prefix>
|
||||||
<docker-maven-plugin.version>1.1.0</docker-maven-plugin.version>
|
<docker-maven-plugin.version>1.1.0</docker-maven-plugin.version>
|
||||||
<azure-webapp-maven-plugin.version>1.1.0</azure-webapp-maven-plugin.version>
|
<azure-webapp-maven-plugin.version>1.1.0</azure-webapp-maven-plugin.version>
|
||||||
<maven-war-plugin.version>3.3.2</maven-war-plugin.version>
|
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
|
@ -27,6 +27,7 @@
|
||||||
<hsqldb.version>2.7.1</hsqldb.version>
|
<hsqldb.version>2.7.1</hsqldb.version>
|
||||||
<spock-core.version>2.3-groovy-3.0</spock-core.version>
|
<spock-core.version>2.3-groovy-3.0</spock-core.version>
|
||||||
<gmavenplus-plugin.version>2.1.0</gmavenplus-plugin.version>
|
<gmavenplus-plugin.version>2.1.0</gmavenplus-plugin.version>
|
||||||
|
<maven-failsafe-plugin.version>2.21.0</maven-failsafe-plugin.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
||||||
|
|
|
@ -1,15 +0,0 @@
|
||||||
package reminderapplication;
|
|
||||||
|
|
||||||
import java.awt.GridBagConstraints;
|
|
||||||
import java.awt.Insets;
|
|
||||||
|
|
||||||
public class ConstraintsBuilder {
|
|
||||||
|
|
||||||
static GridBagConstraints constraint(int x, int y) {
|
|
||||||
final GridBagConstraints gridBagConstraints = new GridBagConstraints();
|
|
||||||
gridBagConstraints.gridx = x;
|
|
||||||
gridBagConstraints.gridy = y;
|
|
||||||
gridBagConstraints.insets = new Insets(5, 5, 5, 5);
|
|
||||||
return gridBagConstraints;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,194 +0,0 @@
|
||||||
package reminderapplication;
|
|
||||||
|
|
||||||
import static reminderapplication.ConstraintsBuilder.*;
|
|
||||||
|
|
||||||
import java.awt.GridBagLayout;
|
|
||||||
import java.awt.HeadlessException;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import javax.swing.DefaultComboBoxModel;
|
|
||||||
import javax.swing.DefaultListModel;
|
|
||||||
import javax.swing.JButton;
|
|
||||||
import javax.swing.JComboBox;
|
|
||||||
import javax.swing.JFrame;
|
|
||||||
import javax.swing.JLabel;
|
|
||||||
import javax.swing.JTextField;
|
|
||||||
import javax.swing.SwingUtilities;
|
|
||||||
|
|
||||||
public class EditReminderFrame extends JFrame {
|
|
||||||
|
|
||||||
private static Timer TIMER = new Timer();
|
|
||||||
|
|
||||||
private final TimeReminderApplication reminderApplication;
|
|
||||||
private final JLabel reminderTextLabel;
|
|
||||||
private final JLabel repeatPeriodLabel;
|
|
||||||
private final JLabel setDelayLabel;
|
|
||||||
private final JComboBox<Integer> delay;
|
|
||||||
private final JComboBox<Integer> period;
|
|
||||||
private final JButton cancelButton;
|
|
||||||
private final JButton okButton;
|
|
||||||
private final JTextField textField;
|
|
||||||
private final JLabel delaysLabel;
|
|
||||||
private final JLabel periodLabel;
|
|
||||||
|
|
||||||
private final int reminderIndex;
|
|
||||||
|
|
||||||
public EditReminderFrame(TimeReminderApplication reminderApp, String reminderText, int delayInSeconds, int periodInSeconds, int index) throws HeadlessException {
|
|
||||||
this.reminderApplication = reminderApp;
|
|
||||||
reminderIndex = index;
|
|
||||||
textField = createTextField(reminderText);
|
|
||||||
delay = createDelayComboBox(delayInSeconds);
|
|
||||||
period = createPeriodComboBox(periodInSeconds);
|
|
||||||
cancelButton = createCancelButton();
|
|
||||||
okButton = createOkButton();
|
|
||||||
reminderTextLabel = createReminderTextLabel();
|
|
||||||
repeatPeriodLabel = createRepeatPeriodLabel();
|
|
||||||
setDelayLabel = createSetDelayLabel();
|
|
||||||
delaysLabel = createDelaysLabel();
|
|
||||||
periodLabel = createPeriodLabel();
|
|
||||||
configureVisualRepresentation();
|
|
||||||
configureActions();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configureActions() {
|
|
||||||
updateReminder();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configureVisualRepresentation() {
|
|
||||||
configureFrame();
|
|
||||||
setLocationRelativeTo(null);
|
|
||||||
setLayout(new GridBagLayout());
|
|
||||||
add(reminderTextLabel, constraint(0,0));
|
|
||||||
add(repeatPeriodLabel, constraint(1,0));
|
|
||||||
add(setDelayLabel, constraint(2,0));
|
|
||||||
add(textField, constraint(0, 1));
|
|
||||||
add(delay, constraint(1, 1));
|
|
||||||
add(period, constraint(2, 1));
|
|
||||||
add(delaysLabel, constraint(1,3));
|
|
||||||
add(periodLabel, constraint(2,3));
|
|
||||||
add(okButton, constraint(1, 4));
|
|
||||||
add(cancelButton, constraint(2, 4));
|
|
||||||
pack();
|
|
||||||
setVisible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configureFrame() {
|
|
||||||
setTitle("Set Reminder");
|
|
||||||
setName("Set Reminder");
|
|
||||||
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JLabel createSetDelayLabel() {
|
|
||||||
return createLabel("Set Delay", "Set Delay Label");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JLabel createRepeatPeriodLabel() {
|
|
||||||
return createLabel("Set Period", "Set Repeat Period Label");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JLabel createReminderTextLabel() {
|
|
||||||
return createLabel("Reminder Text", "Reminder Text Label");
|
|
||||||
}
|
|
||||||
|
|
||||||
private JLabel createPeriodLabel() {
|
|
||||||
return createLabel("0", "Period label");
|
|
||||||
}
|
|
||||||
|
|
||||||
private JLabel createDelaysLabel() {
|
|
||||||
return createLabel("30", "Delays Label");
|
|
||||||
}
|
|
||||||
|
|
||||||
private JComboBox<Integer> createPeriodComboBox(final int periodInSeconds) {
|
|
||||||
final JComboBox<Integer> comboBox = new JComboBox<>(new DefaultComboBoxModel<>(new Integer[]{0, 5, 10, 20}));
|
|
||||||
comboBox.setSelectedItem(periodInSeconds);
|
|
||||||
comboBox.setName("set Period");
|
|
||||||
comboBox.addActionListener(e -> periodLabel.setText(comboBox.getSelectedItem().toString()));
|
|
||||||
return comboBox;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JComboBox<Integer> createDelayComboBox(final int delayInSeconds) {
|
|
||||||
final JComboBox<Integer> comboBox = new JComboBox<>(new DefaultComboBoxModel<>(new Integer[]{30, 25, 15, 5}));
|
|
||||||
comboBox.setSelectedItem(delayInSeconds);
|
|
||||||
comboBox.setName("set Delay");
|
|
||||||
comboBox.addActionListener(e -> delaysLabel.setText(comboBox.getSelectedItem().toString()));
|
|
||||||
return comboBox;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JTextField createTextField(final String reminderText) {
|
|
||||||
final JTextField textField = new JTextField(20);
|
|
||||||
textField.setName("Field");
|
|
||||||
textField.setText(reminderText);
|
|
||||||
return textField;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JButton createOkButton() {
|
|
||||||
final JButton button = new JButton("ok");
|
|
||||||
button.setName("OK");
|
|
||||||
return button;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void updateReminder() {
|
|
||||||
okButton.addActionListener(e -> this.dispose());
|
|
||||||
okButton.addActionListener(e -> {
|
|
||||||
final int periodInSeconds = getTimeInSeconds(period);
|
|
||||||
final int delayInSeconds = getTimeInSeconds(delay);
|
|
||||||
final Reminder reminder = new Reminder(textField.getText(), delayInSeconds, periodInSeconds);
|
|
||||||
((DefaultListModel<Reminder>) reminderApplication.getReminders()).set(reminderIndex, reminder);
|
|
||||||
});
|
|
||||||
okButton.addActionListener(e -> scheduleReminder(textField, delay, period));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void scheduleReminder(final JTextField textField, final JComboBox<Integer> delay, final JComboBox<Integer> period) {
|
|
||||||
final int periodInSeconds = getTimeInSeconds(period);
|
|
||||||
if (periodInSeconds == 0)
|
|
||||||
scheduleNonRepeatedReminder(textField, delay);
|
|
||||||
else
|
|
||||||
scheduleRepeatedReminder(textField, delay, period);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void scheduleRepeatedReminder(final JTextField textField, final JComboBox<Integer> delay, final JComboBox<Integer> period) {
|
|
||||||
final int delayInSeconds = getTimeInSeconds(delay);
|
|
||||||
final int periodInSeconds = getTimeInSeconds(period);
|
|
||||||
final TimerTask timerTask = getTimerTask(textField.getText(), delayInSeconds, periodInSeconds);
|
|
||||||
TIMER.schedule(timerTask, TimeUnit.SECONDS.toMillis(delayInSeconds), TimeUnit.SECONDS.toMillis(periodInSeconds));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void scheduleNonRepeatedReminder(final JTextField textField, final JComboBox<Integer> delay) {
|
|
||||||
final int delayInSeconds = getTimeInSeconds(delay);
|
|
||||||
final int periodInSeconds = 0;
|
|
||||||
final TimerTask timerTask = getTimerTask(textField.getText(), delayInSeconds, periodInSeconds);
|
|
||||||
TIMER.schedule(timerTask, TimeUnit.SECONDS.toMillis(delayInSeconds));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getTimeInSeconds(final JComboBox<Integer> comboBox) {
|
|
||||||
if (comboBox != null && comboBox.getSelectedItem() != null)
|
|
||||||
return ((Integer) comboBox.getSelectedItem());
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private TimerTask getTimerTask(final String reminderText, final Integer delayInSeconds, final Integer periodInSeconds) {
|
|
||||||
return new TimerTask() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
new ReminderPopupFrame(reminderApplication, reminderText, delayInSeconds, periodInSeconds);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private JButton createCancelButton() {
|
|
||||||
final JButton button = new JButton("cancel");
|
|
||||||
button.setName("Cancel");
|
|
||||||
button.addActionListener(e -> this.dispose());
|
|
||||||
return button;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JLabel createLabel(final String text, final String name) {
|
|
||||||
JLabel label = new JLabel(text);
|
|
||||||
label.setName(name);
|
|
||||||
return label;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,33 +0,0 @@
|
||||||
package reminderapplication;
|
|
||||||
|
|
||||||
public class Reminder {
|
|
||||||
|
|
||||||
private static String REMINDER_FORMAT = "Reminder Text: %s; Delay: %d; Period: %d;";
|
|
||||||
|
|
||||||
private final String name;
|
|
||||||
private final int delay;
|
|
||||||
private final int period;
|
|
||||||
|
|
||||||
public Reminder(final String name, final int delay, final int period) {
|
|
||||||
this.name = name;
|
|
||||||
this.delay = delay;
|
|
||||||
this.period = period;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getName() {
|
|
||||||
return name;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getDelay() {
|
|
||||||
return delay;
|
|
||||||
}
|
|
||||||
|
|
||||||
public int getPeriod() {
|
|
||||||
return period;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return REMINDER_FORMAT.formatted(name, delay, period);
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,186 +0,0 @@
|
||||||
package reminderapplication;
|
|
||||||
|
|
||||||
import static reminderapplication.ConstraintsBuilder.*;
|
|
||||||
|
|
||||||
import java.awt.GridBagLayout;
|
|
||||||
import java.awt.HeadlessException;
|
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import javax.swing.DefaultComboBoxModel;
|
|
||||||
import javax.swing.DefaultListModel;
|
|
||||||
import javax.swing.JButton;
|
|
||||||
import javax.swing.JComboBox;
|
|
||||||
import javax.swing.JFrame;
|
|
||||||
import javax.swing.JLabel;
|
|
||||||
import javax.swing.JTextField;
|
|
||||||
|
|
||||||
public class ReminderFrame extends JFrame {
|
|
||||||
|
|
||||||
private static Timer TIMER = new Timer();
|
|
||||||
private final TimeReminderApplication reminderApplication;
|
|
||||||
private final JLabel reminderTextLabel;
|
|
||||||
private final JLabel repeatPeriodLabel;
|
|
||||||
private final JLabel setDelayLabel;
|
|
||||||
private final JComboBox<Integer> delay;
|
|
||||||
private final JComboBox<Integer> period;
|
|
||||||
private final JButton cancelButton;
|
|
||||||
private final JButton okButton;
|
|
||||||
private final JTextField textField;
|
|
||||||
private final JLabel delaysLabel;
|
|
||||||
private final JLabel periodLabel;
|
|
||||||
|
|
||||||
public ReminderFrame(TimeReminderApplication reminderApp) throws HeadlessException {
|
|
||||||
this.reminderApplication = reminderApp;
|
|
||||||
textField = createTextField();
|
|
||||||
delay = createDelayComboBox();
|
|
||||||
period = createPeriodComboBox();
|
|
||||||
cancelButton = createCancelButton();
|
|
||||||
okButton = createOkButton();
|
|
||||||
reminderTextLabel = createReminderTextLabel();
|
|
||||||
repeatPeriodLabel = createRepeatPeriodLabel();
|
|
||||||
setDelayLabel = createSetDelayLabel();
|
|
||||||
delaysLabel = createDelaysLabel();
|
|
||||||
periodLabel = createPeriodLabel();
|
|
||||||
configureVisualRepresentation();
|
|
||||||
configureActions();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configureActions() {
|
|
||||||
createNewReminder();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configureVisualRepresentation() {
|
|
||||||
configureFrame();
|
|
||||||
setLocationRelativeTo(null);
|
|
||||||
setLayout(new GridBagLayout());
|
|
||||||
add(reminderTextLabel, constraint(0,0));
|
|
||||||
add(repeatPeriodLabel, constraint(1,0));
|
|
||||||
add(setDelayLabel, constraint(2,0));
|
|
||||||
add(textField, constraint(0, 1));
|
|
||||||
add(delay, constraint(1, 1));
|
|
||||||
add(period, constraint(2, 1));
|
|
||||||
add(delaysLabel, constraint(1,3));
|
|
||||||
add(periodLabel, constraint(2,3));
|
|
||||||
add(okButton, constraint(1, 4));
|
|
||||||
add(cancelButton, constraint(2, 4));
|
|
||||||
pack();
|
|
||||||
setVisible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configureFrame() {
|
|
||||||
setTitle("Set Reminder");
|
|
||||||
setName("Set Reminder");
|
|
||||||
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JLabel createSetDelayLabel() {
|
|
||||||
return createLabel("Set Delay", "Set Delay Label");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JLabel createRepeatPeriodLabel() {
|
|
||||||
return createLabel("Set Period", "Set Repeat Period Label");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JLabel createReminderTextLabel() {
|
|
||||||
return createLabel("Reminder Text", "Reminder Text Label");
|
|
||||||
}
|
|
||||||
|
|
||||||
private JLabel createPeriodLabel() {
|
|
||||||
return createLabel("0", "Period label");
|
|
||||||
}
|
|
||||||
|
|
||||||
private JLabel createDelaysLabel() {
|
|
||||||
return createLabel("30", "Delays Label");
|
|
||||||
}
|
|
||||||
|
|
||||||
private JComboBox<Integer> createPeriodComboBox() {
|
|
||||||
final JComboBox<Integer> comboBox = new JComboBox<>(new DefaultComboBoxModel<>(new Integer[]{0, 5, 10, 20}));
|
|
||||||
comboBox.setName("set Period");
|
|
||||||
comboBox.addActionListener(e -> periodLabel.setText(comboBox.getSelectedItem().toString()));
|
|
||||||
return comboBox;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JComboBox<Integer> createDelayComboBox() {
|
|
||||||
final JComboBox<Integer> comboBox = new JComboBox<>(new DefaultComboBoxModel<>(new Integer[]{30, 25, 15, 5}));
|
|
||||||
comboBox.setName("set Delay");
|
|
||||||
comboBox.addActionListener(e -> delaysLabel.setText(comboBox.getSelectedItem().toString()));
|
|
||||||
return comboBox;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JTextField createTextField() {
|
|
||||||
final JTextField textField = new JTextField(20);
|
|
||||||
textField.setName("Field");
|
|
||||||
return textField;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JButton createOkButton() {
|
|
||||||
final JButton button = new JButton("ok");
|
|
||||||
button.setName("OK");
|
|
||||||
return button;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void createNewReminder() {
|
|
||||||
|
|
||||||
okButton.addActionListener(e -> this.dispose());
|
|
||||||
okButton.addActionListener(e -> {
|
|
||||||
final int periodInSeconds = getTimeInSeconds(period);
|
|
||||||
final int delayInSeconds = getTimeInSeconds(delay);
|
|
||||||
final Reminder reminder = new Reminder(textField.getText(), delayInSeconds, periodInSeconds);
|
|
||||||
((DefaultListModel<Reminder>) reminderApplication.getReminders()).addElement(reminder);
|
|
||||||
});
|
|
||||||
okButton.addActionListener(e -> scheduleReminder(textField, delay, period));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void scheduleReminder(final JTextField textField, final JComboBox<Integer> delay, final JComboBox<Integer> period) {
|
|
||||||
final int periodInSeconds = getTimeInSeconds(period);
|
|
||||||
if (periodInSeconds == 0)
|
|
||||||
scheduleNonRepeatedReminder(textField, delay);
|
|
||||||
else
|
|
||||||
scheduleRepeatedReminder(textField, delay, period);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void scheduleRepeatedReminder(final JTextField textField, final JComboBox<Integer> delay, final JComboBox<Integer> period) {
|
|
||||||
final int delayInSeconds = getTimeInSeconds(delay) + 200;
|
|
||||||
final int periodInSeconds = getTimeInSeconds(period);
|
|
||||||
final TimerTask timerTask = getTimerTask(textField.getText(), delayInSeconds, periodInSeconds);
|
|
||||||
TIMER.schedule(timerTask, TimeUnit.SECONDS.toMillis(delayInSeconds), TimeUnit.SECONDS.toMillis(periodInSeconds));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void scheduleNonRepeatedReminder(final JTextField textField, final JComboBox<Integer> delay) {
|
|
||||||
final int delayInSeconds = getTimeInSeconds(delay);
|
|
||||||
final int periodInSeconds = 0;
|
|
||||||
final TimerTask timerTask = getTimerTask(textField.getText(), delayInSeconds, periodInSeconds);
|
|
||||||
TIMER.schedule(timerTask, TimeUnit.SECONDS.toMillis(delayInSeconds));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
private int getTimeInSeconds(final JComboBox<Integer> comboBox) {
|
|
||||||
if (comboBox != null && comboBox.getSelectedItem() != null)
|
|
||||||
return ((Integer) comboBox.getSelectedItem());
|
|
||||||
else
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
private TimerTask getTimerTask(final String reminderText, final Integer delayInSeconds, final Integer periodInSeconds) {
|
|
||||||
return new TimerTask() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
new ReminderPopupFrame(reminderApplication, reminderText, delayInSeconds, periodInSeconds);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private JButton createCancelButton() {
|
|
||||||
final JButton button = new JButton("cancel");
|
|
||||||
button.setName("Cancel");
|
|
||||||
button.addActionListener(e -> this.dispose());
|
|
||||||
return button;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JLabel createLabel(final String text, final String name) {
|
|
||||||
JLabel label = new JLabel(text);
|
|
||||||
label.setName(name);
|
|
||||||
return label;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,151 +0,0 @@
|
||||||
package reminderapplication;
|
|
||||||
|
|
||||||
import static reminderapplication.ConstraintsBuilder.*;
|
|
||||||
|
|
||||||
import java.awt.GridBagLayout;
|
|
||||||
import java.awt.HeadlessException;
|
|
||||||
import java.util.Timer;
|
|
||||||
import java.util.TimerTask;
|
|
||||||
import java.util.concurrent.TimeUnit;
|
|
||||||
import javax.swing.DefaultComboBoxModel;
|
|
||||||
import javax.swing.DefaultListModel;
|
|
||||||
import javax.swing.JButton;
|
|
||||||
import javax.swing.JComboBox;
|
|
||||||
import javax.swing.JFrame;
|
|
||||||
import javax.swing.JLabel;
|
|
||||||
import javax.swing.JTextField;
|
|
||||||
|
|
||||||
public class ReminderPopupFrame extends JFrame {
|
|
||||||
|
|
||||||
private static final Timer TIMER = new Timer();
|
|
||||||
private final int AUTOMATIC_CLOSE_TIME_IN_SECONDS = 10;
|
|
||||||
private final TimeReminderApplication reminderApplication;
|
|
||||||
private final JLabel reminderTextLabel;
|
|
||||||
private final JLabel repeatPeriodLabel;
|
|
||||||
private final JLabel setDelayLabel;
|
|
||||||
private final JComboBox<Integer> delay;
|
|
||||||
private final JComboBox<Integer> period;
|
|
||||||
private final JButton cancelButton;
|
|
||||||
private final JButton okButton;
|
|
||||||
private final JTextField textField;
|
|
||||||
private final JLabel delaysLabel;
|
|
||||||
private final JLabel periodLabel;
|
|
||||||
|
|
||||||
public ReminderPopupFrame(TimeReminderApplication reminderApp, final String text, final Integer delayInSeconds, final Integer periodInSeconds) throws HeadlessException {
|
|
||||||
this.reminderApplication = reminderApp;
|
|
||||||
textField = createTextField(text);
|
|
||||||
delay = createDelayComboBox(delayInSeconds);
|
|
||||||
period = createPeriodComboBox(periodInSeconds);
|
|
||||||
cancelButton = createCancelButton();
|
|
||||||
okButton = createDisabledOkButton();
|
|
||||||
reminderTextLabel = createReminderTextLabel();
|
|
||||||
repeatPeriodLabel = createRepeatPeriodLabel();
|
|
||||||
setDelayLabel = createSetDelayLabel();
|
|
||||||
delaysLabel = createDelaysLabel();
|
|
||||||
periodLabel = createPeriodLabel();
|
|
||||||
configureVisualRepresentation();
|
|
||||||
configureActions();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configureActions() {
|
|
||||||
scheduleClosing();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void scheduleClosing() {
|
|
||||||
final TimerTask timerTask = new TimerTask() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
ReminderPopupFrame.this.dispose();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
TIMER.schedule(timerTask, TimeUnit.SECONDS.toMillis(AUTOMATIC_CLOSE_TIME_IN_SECONDS));
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configureVisualRepresentation() {
|
|
||||||
configureFrame();
|
|
||||||
setLocationRelativeTo(null);
|
|
||||||
setLayout(new GridBagLayout());
|
|
||||||
add(reminderTextLabel, constraint(0,0));
|
|
||||||
add(repeatPeriodLabel, constraint(1,0));
|
|
||||||
add(setDelayLabel, constraint(2,0));
|
|
||||||
add(textField, constraint(0, 1));
|
|
||||||
add(delay, constraint(1, 1));
|
|
||||||
add(period, constraint(2, 1));
|
|
||||||
add(delaysLabel, constraint(1,3));
|
|
||||||
add(periodLabel, constraint(2,3));
|
|
||||||
add(okButton, constraint(1, 4));
|
|
||||||
add(cancelButton, constraint(2, 4));
|
|
||||||
pack();
|
|
||||||
setVisible(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void configureFrame() {
|
|
||||||
setTitle("Set Reminder");
|
|
||||||
setName("Set Reminder");
|
|
||||||
setDefaultCloseOperation(DISPOSE_ON_CLOSE);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JLabel createSetDelayLabel() {
|
|
||||||
return createLabel("Set Delay", "Set Delay Label");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JLabel createRepeatPeriodLabel() {
|
|
||||||
return createLabel("Set Period", "Set Repeat Period Label");
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JLabel createReminderTextLabel() {
|
|
||||||
return createLabel("Reminder Text", "Reminder Text Label");
|
|
||||||
}
|
|
||||||
|
|
||||||
private JLabel createPeriodLabel() {
|
|
||||||
return createLabel("0", "Period label");
|
|
||||||
}
|
|
||||||
|
|
||||||
private JLabel createDelaysLabel() {
|
|
||||||
return createLabel("30", "Delays Label");
|
|
||||||
}
|
|
||||||
|
|
||||||
private JComboBox<Integer> createPeriodComboBox(final Integer periodInSeconds) {
|
|
||||||
final JComboBox<Integer> comboBox = new JComboBox<>(new DefaultComboBoxModel<>(new Integer[]{0, 5, 10, 20}));
|
|
||||||
comboBox.setName("set Period");
|
|
||||||
comboBox.setSelectedItem(periodInSeconds);
|
|
||||||
comboBox.addActionListener(e -> periodLabel.setText(comboBox.getSelectedItem().toString()));
|
|
||||||
return comboBox;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JComboBox<Integer> createDelayComboBox(Integer delay) {
|
|
||||||
final JComboBox<Integer> comboBox = new JComboBox<>(new DefaultComboBoxModel<>(new Integer[]{30, 25, 15, 5}));
|
|
||||||
comboBox.setSelectedItem(delay);
|
|
||||||
comboBox.setName("set Delay");
|
|
||||||
comboBox.addActionListener(e -> delaysLabel.setText(comboBox.getSelectedItem().toString()));
|
|
||||||
return comboBox;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JTextField createTextField(final String text) {
|
|
||||||
final JTextField textField = new JTextField(20);
|
|
||||||
textField.setName("Field");
|
|
||||||
textField.setText(text);
|
|
||||||
return textField;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JButton createDisabledOkButton() {
|
|
||||||
final JButton button = new JButton("ok");
|
|
||||||
button.setName("OK");
|
|
||||||
button.setEnabled(false);
|
|
||||||
return button;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JButton createCancelButton() {
|
|
||||||
final JButton button = new JButton("cancel");
|
|
||||||
button.setName("Cancel");
|
|
||||||
button.addActionListener(e -> this.dispose());
|
|
||||||
return button;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static JLabel createLabel(final String text, final String name) {
|
|
||||||
JLabel label = new JLabel(text);
|
|
||||||
label.setName(name);
|
|
||||||
return label;
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
|
@ -48,7 +48,6 @@
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<maven.compiler.release>14</maven.compiler.release>
|
<maven.compiler.release>14</maven.compiler.release>
|
||||||
<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
|
|
||||||
<surefire.plugin.version>3.0.0-M3</surefire.plugin.version>
|
<surefire.plugin.version>3.0.0-M3</surefire.plugin.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,6 @@
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
<maven.compiler.release>15</maven.compiler.release>
|
<maven.compiler.release>15</maven.compiler.release>
|
||||||
<maven-compiler-plugin.version>3.8.1</maven-compiler-plugin.version>
|
|
||||||
<surefire.plugin.version>3.0.0-M3</surefire.plugin.version>
|
<surefire.plugin.version>3.0.0-M3</surefire.plugin.version>
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
|
|
|
@ -7,3 +7,4 @@
|
||||||
- [Random Number Generators in Java 17](https://www.baeldung.com/java-17-random-number-generators)
|
- [Random Number Generators in Java 17](https://www.baeldung.com/java-17-random-number-generators)
|
||||||
- [Sealed Classes and Interfaces in Java](https://www.baeldung.com/java-sealed-classes-interfaces)
|
- [Sealed Classes and Interfaces in Java](https://www.baeldung.com/java-sealed-classes-interfaces)
|
||||||
- [Migrate From Java 8 to Java 17](https://www.baeldung.com/java-migrate-8-to-17)
|
- [Migrate From Java 8 to Java 17](https://www.baeldung.com/java-migrate-8-to-17)
|
||||||
|
- [Format Multiple ‘or’ Conditions in an If Statement in Java](https://www.baeldung.com/java-multiple-or-conditions-if-statement)
|
||||||
|
|
|
@ -0,0 +1,126 @@
|
||||||
|
package com.baeldung.multipleorwithif;
|
||||||
|
|
||||||
|
import static java.time.Month.DECEMBER;
|
||||||
|
import static java.time.Month.NOVEMBER;
|
||||||
|
import static java.time.Month.OCTOBER;
|
||||||
|
import static org.hamcrest.MatcherAssert.assertThat;
|
||||||
|
import static org.hamcrest.Matchers.in;
|
||||||
|
import static org.hamcrest.Matchers.is;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
import java.time.Month;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Random;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.function.Predicate;
|
||||||
|
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
class MultipleOrWithIfUnitTest {
|
||||||
|
|
||||||
|
private final Random rand = new Random();
|
||||||
|
|
||||||
|
final Set<Month> months = Set.of(OCTOBER, NOVEMBER, DECEMBER);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenIfStatement_whenMultipleOrOperator_thenAssert() {
|
||||||
|
assertTrue(multipleOrOperatorIf(monthIn()));
|
||||||
|
assertFalse(multipleOrOperatorIf(monthNotIn()));
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean multipleOrOperatorIf(Month month) {
|
||||||
|
if (month == OCTOBER || month == NOVEMBER || month == DECEMBER) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenSwitch_whenMultipleCase_thenBreakAndAssert() {
|
||||||
|
assertTrue(switchMonth(monthIn()));
|
||||||
|
assertFalse(switchMonth(monthNotIn()));
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean switchMonth(Month month) {
|
||||||
|
return switch (month) {
|
||||||
|
case OCTOBER, NOVEMBER, DECEMBER -> true;
|
||||||
|
default -> false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenAllowedValuesList_whenContains_thenAssert() {
|
||||||
|
assertTrue(contains(monthIn()));
|
||||||
|
assertFalse(contains(monthNotIn()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenPredicates_whenTestMultipleOr_thenAssert() {
|
||||||
|
assertTrue(predicateWithIf(monthIn()));
|
||||||
|
assertFalse(predicateWithIf(monthNotIn()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenInputList_whenFilterWithPredicate_thenAssert() {
|
||||||
|
|
||||||
|
List<Month> list = List.of(monthIn(), monthIn(), monthNotIn());
|
||||||
|
|
||||||
|
list.stream()
|
||||||
|
.filter(this::predicateWithIf)
|
||||||
|
.forEach(m -> assertThat(m, is(in(months))));
|
||||||
|
}
|
||||||
|
|
||||||
|
Predicate<Month> orPredicate() {
|
||||||
|
Predicate<Month> predicate = x -> x == OCTOBER;
|
||||||
|
Predicate<Month> predicate1 = x -> x == NOVEMBER;
|
||||||
|
Predicate<Month> predicate2 = x -> x == DECEMBER;
|
||||||
|
|
||||||
|
return predicate.or(predicate1)
|
||||||
|
.or(predicate2);
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean predicateWithIf(Month month) {
|
||||||
|
if (orPredicate().test(month)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenContainsInSetPredicate_whenTestPredicate_thenAssert() {
|
||||||
|
Predicate<Month> collectionPredicate = this::contains;
|
||||||
|
|
||||||
|
assertTrue(collectionPredicate.test(monthIn()));
|
||||||
|
assertFalse(collectionPredicate.test(monthNotIn()));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenInputList_whenFilterWithContains_thenAssert() {
|
||||||
|
|
||||||
|
List<Month> monthList = List.of(monthIn(), monthIn(), monthNotIn());
|
||||||
|
|
||||||
|
monthList.stream()
|
||||||
|
.filter(this::contains)
|
||||||
|
.forEach(m -> assertThat(m, is(in(months))));
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean contains(Month month) {
|
||||||
|
if (months.contains(month)) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Month monthIn() {
|
||||||
|
return Month.of(rand.ints(10, 13)
|
||||||
|
.findFirst()
|
||||||
|
.orElse(10));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Month monthNotIn() {
|
||||||
|
return Month.of(rand.ints(1, 10)
|
||||||
|
.findFirst()
|
||||||
|
.orElse(1));
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
## Relevant Articles
|
|
@ -0,0 +1,34 @@
|
||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
|
<modelVersion>4.0.0</modelVersion>
|
||||||
|
<artifactId>core-java-21</artifactId>
|
||||||
|
<name>core-java-21</name>
|
||||||
|
|
||||||
|
<parent>
|
||||||
|
<groupId>com.baeldung.core-java-modules</groupId>
|
||||||
|
<artifactId>core-java-modules</artifactId>
|
||||||
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
|
</parent>
|
||||||
|
|
||||||
|
<!-- <build>-->
|
||||||
|
<!-- <plugins>-->
|
||||||
|
<!-- <plugin>-->
|
||||||
|
<!-- <groupId>org.apache.maven.plugins</groupId>-->
|
||||||
|
<!-- <artifactId>maven-compiler-plugin</artifactId>-->
|
||||||
|
<!-- <configuration>-->
|
||||||
|
<!-- <source>{maven.compiler.source.version}</source>-->
|
||||||
|
<!-- <target>{maven.compiler.target.version}</target>-->
|
||||||
|
<!-- </configuration>-->
|
||||||
|
<!-- </plugin>-->
|
||||||
|
<!-- </plugins>-->
|
||||||
|
<!-- </build>-->
|
||||||
|
|
||||||
|
<!-- <properties>-->
|
||||||
|
<!-- <maven.compiler.source.version>21</maven.compiler.source.version>-->
|
||||||
|
<!-- <maven.compiler.target.version>21</maven.compiler.target.version>-->
|
||||||
|
<!-- <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>-->
|
||||||
|
<!-- </properties>-->
|
||||||
|
|
||||||
|
</project>
|
|
@ -0,0 +1,15 @@
|
||||||
|
package com.baeldung.sequenced.collections;
|
||||||
|
|
||||||
|
/*
|
||||||
|
interface SequencedCollection<E> extends Collection<E> {
|
||||||
|
// new method
|
||||||
|
SequencedCollection<E> reversed();
|
||||||
|
// methods promoted from Deque
|
||||||
|
void addFirst(E);
|
||||||
|
void addLast(E);
|
||||||
|
E getFirst();
|
||||||
|
E getLast();
|
||||||
|
E removeFirst();
|
||||||
|
E removeLast();
|
||||||
|
}
|
||||||
|
*/
|
|
@ -0,0 +1,18 @@
|
||||||
|
package com.baeldung.sequenced.collections;
|
||||||
|
|
||||||
|
/*
|
||||||
|
interface SequencedMap<K,V> extends Map<K,V> {
|
||||||
|
// new methods
|
||||||
|
SequencedMap<K,V> reversed();
|
||||||
|
SequencedSet<K> sequencedKeySet();
|
||||||
|
SequencedCollection<V> sequencedValues();
|
||||||
|
SequencedSet<Entry<K,V>> sequencedEntrySet();
|
||||||
|
V putFirst(K, V);
|
||||||
|
V putLast(K, V);
|
||||||
|
// methods promoted from NavigableMap
|
||||||
|
Entry<K, V> firstEntry();
|
||||||
|
Entry<K, V> lastEntry();
|
||||||
|
Entry<K, V> pollFirstEntry();
|
||||||
|
Entry<K, V> pollLastEntry();
|
||||||
|
}
|
||||||
|
*/
|
|
@ -0,0 +1,7 @@
|
||||||
|
package com.baeldung.sequenced.collections;
|
||||||
|
|
||||||
|
/*
|
||||||
|
interface SequencedSet<E> extends Set<E>, SequencedCollection<E> {
|
||||||
|
SequencedSet<E> reversed(); // covariant override
|
||||||
|
}
|
||||||
|
*/
|
|
@ -0,0 +1,37 @@
|
||||||
|
package com.baeldung.stringtime;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.*;
|
||||||
|
|
||||||
|
import java.text.ParseException;
|
||||||
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.time.LocalTime;
|
||||||
|
import java.util.Calendar;
|
||||||
|
import java.util.Date;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
public class AddMinuteStringTimeUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenTimeStringUsingSimpleDateFormat_whenIncrementedWith10Minutes_thenResultShouldBeCorrect() throws ParseException {
|
||||||
|
String timeString = "23:45";
|
||||||
|
SimpleDateFormat timeFormat = new SimpleDateFormat("HH:mm");
|
||||||
|
Date date = timeFormat.parse(timeString);
|
||||||
|
|
||||||
|
Calendar cal = Calendar.getInstance();
|
||||||
|
cal.setTime(date);
|
||||||
|
cal.add(Calendar.MINUTE, 10);
|
||||||
|
String result = timeFormat.format(cal.getTime());
|
||||||
|
assertEquals("23:55", result);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenTimeStringUsingLocalTime_whenIncrementedWith10Minutes_thenResultShouldBeCorrect() {
|
||||||
|
String timeString = "23:45";
|
||||||
|
LocalTime time = LocalTime.parse(timeString);
|
||||||
|
LocalTime newTime = time.plusMinutes(10);
|
||||||
|
String result = newTime.toString();
|
||||||
|
assertEquals("23:55", result);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -10,7 +10,7 @@
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>parent-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>1.0.0-SNAPSHOT</version>
|
||||||
<relativePath>../../</relativePath>
|
<relativePath>../../pom.xml</relativePath>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<dependencies>
|
<dependencies>
|
||||||
|
|
|
@ -4,9 +4,9 @@
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung.core-java-modules</groupId>
|
||||||
<artifactId>core-java-9-jigsaw</artifactId>
|
<artifactId>core-java-9-jigsaw</artifactId>
|
||||||
<version>0.2-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<artifactId>library-core</artifactId>
|
<artifactId>library-core</artifactId>
|
||||||
|
|
|
@ -11,10 +11,9 @@
|
||||||
</modules>
|
</modules>
|
||||||
|
|
||||||
<parent>
|
<parent>
|
||||||
<groupId>com.baeldung</groupId>
|
<groupId>com.baeldung.core-java-modules</groupId>
|
||||||
<artifactId>parent-modules</artifactId>
|
<artifactId>core-java-modules</artifactId>
|
||||||
<version>1.0.0-SNAPSHOT</version>
|
<version>0.0.1-SNAPSHOT</version>
|
||||||
<relativePath>../../</relativePath>
|
|
||||||
</parent>
|
</parent>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
@ -152,7 +152,6 @@
|
||||||
<awaitility.version>4.0.2</awaitility.version>
|
<awaitility.version>4.0.2</awaitility.version>
|
||||||
<maven.compiler.source>1.9</maven.compiler.source>
|
<maven.compiler.source>1.9</maven.compiler.source>
|
||||||
<maven.compiler.target>1.9</maven.compiler.target>
|
<maven.compiler.target>1.9</maven.compiler.target>
|
||||||
<maven-jar-plugin.version>3.2.0</maven-jar-plugin.version>
|
|
||||||
</properties>
|
</properties>
|
||||||
|
|
||||||
</project>
|
</project>
|
|
@ -0,0 +1,16 @@
|
||||||
|
package com.baeldung.streams.regexmatches;
|
||||||
|
|
||||||
|
import java.util.regex.MatchResult;
|
||||||
|
import java.util.regex.Matcher;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
public class StreamFromRegexUtil {
|
||||||
|
|
||||||
|
public static Stream<String> getStream(String input, String regex) {
|
||||||
|
Pattern pattern = Pattern.compile(regex);
|
||||||
|
Matcher matcher = pattern.matcher(input);
|
||||||
|
return matcher.results().map(MatchResult::group);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
package com.baeldung.streams.regexmatches;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import static java.util.Arrays.asList;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
public class StreamFromRegexUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenInputStringIncludeLettersAndNumbersAndRegex_ThenReturnStreamOfNumbers() {
|
||||||
|
List<String> result = StreamFromRegexUtil.getStream("There are 3 apples and 2 bananas on the table.", "\\d+")
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
assertEquals(asList("3", "2"), result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenInputStringsAndRegex_ThenReturnStreamOfJavaWords() {
|
||||||
|
List<String> result = StreamFromRegexUtil.getStream("sample sentence with some words Java Java", "\\bJava\\b")
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
assertEquals(asList("Java", "Java"), result);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -13,3 +13,5 @@ This module contains articles about advanced operations on arrays in Java. They
|
||||||
- [Performance of System.arraycopy() vs. Arrays.copyOf()](https://www.baeldung.com/java-system-arraycopy-arrays-copyof-performance)
|
- [Performance of System.arraycopy() vs. Arrays.copyOf()](https://www.baeldung.com/java-system-arraycopy-arrays-copyof-performance)
|
||||||
- [Slicing Arrays in Java](https://www.baeldung.com/java-slicing-arrays)
|
- [Slicing Arrays in Java](https://www.baeldung.com/java-slicing-arrays)
|
||||||
- [Combining Two or More Byte Arrays](https://www.baeldung.com/java-concatenate-byte-arrays)
|
- [Combining Two or More Byte Arrays](https://www.baeldung.com/java-concatenate-byte-arrays)
|
||||||
|
- [Calculating the Sum of Two Arrays in Java](https://www.baeldung.com/java-sum-arrays-element-wise)
|
||||||
|
- [Find the Middle Element of an Array in Java](https://www.baeldung.com/java-array-middle-item)
|
||||||
|
|
|
@ -0,0 +1,65 @@
|
||||||
|
package com.baeldung.arraymiddle;
|
||||||
|
|
||||||
|
import java.util.Arrays;
|
||||||
|
|
||||||
|
import org.apache.commons.lang3.ObjectUtils;
|
||||||
|
|
||||||
|
public class MiddleOfArray {
|
||||||
|
int[] middleOfArray(int[] array) {
|
||||||
|
if (ObjectUtils.isEmpty(array) || array.length < 3)
|
||||||
|
return array;
|
||||||
|
int n = array.length;
|
||||||
|
int mid = n / 2;
|
||||||
|
if (n % 2 == 0) {
|
||||||
|
int mid2 = mid - 1;
|
||||||
|
return new int[] { array[mid2], array[mid] };
|
||||||
|
} else {
|
||||||
|
return new int[] { array[mid] };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int[] middleOfArrayWithStartEndNaive(int[] array, int start, int end) {
|
||||||
|
int mid = (start + end) / 2;
|
||||||
|
int n = end - start;
|
||||||
|
if (n % 2 == 0) {
|
||||||
|
int mid2 = mid - 1;
|
||||||
|
return new int[] { array[mid2], array[mid] };
|
||||||
|
} else {
|
||||||
|
return new int[] { array[mid] };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int[] middleOfArrayWithStartEnd(int[] array, int start, int end) {
|
||||||
|
int mid = start + (end - start) / 2;
|
||||||
|
int n = end - start;
|
||||||
|
if (n % 2 == 0) {
|
||||||
|
int mid2 = mid - 1;
|
||||||
|
return new int[] { array[mid2], array[mid] };
|
||||||
|
} else {
|
||||||
|
return new int[] { array[mid] };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int[] middleOfArrayWithStartEndBitwise(int[] array, int start, int end) {
|
||||||
|
int mid = (start + end) >>> 1;
|
||||||
|
int n = end - start;
|
||||||
|
if (n % 2 == 0) {
|
||||||
|
int mid2 = mid - 1;
|
||||||
|
return new int[] { array[mid2], array[mid] };
|
||||||
|
} else {
|
||||||
|
return new int[] { array[mid] };
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int medianOfArray(int[] array, int start, int end) {
|
||||||
|
Arrays.sort(array); // for safety. This can be ignored
|
||||||
|
int mid = (start + end) >>> 1;
|
||||||
|
int n = end - start;
|
||||||
|
if (n % 2 == 0) {
|
||||||
|
int mid2 = mid - 1;
|
||||||
|
return (array[mid2] + array[mid]) / 2;
|
||||||
|
} else {
|
||||||
|
return array[mid];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,89 @@
|
||||||
|
package com.baeldung.arraymiddle;
|
||||||
|
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class MiddleOfArrayUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenArrayOfEvenLength_whenMiddleOfArray_thenReturn2Values() {
|
||||||
|
int[] array = new int[100];
|
||||||
|
for (int i = 0; i < array.length; i++) {
|
||||||
|
array[i] = i + 1;
|
||||||
|
}
|
||||||
|
int[] expectedMidArray = { 50, 51 };
|
||||||
|
MiddleOfArray middleOfArray = new MiddleOfArray();
|
||||||
|
Assert.assertArrayEquals(expectedMidArray, middleOfArray.middleOfArray(array));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenArrayOfEdgeCaseLength_whenMiddleOfArray_thenReturn2Values() {
|
||||||
|
int[] array = new int[0];
|
||||||
|
int[] expectedMidArray = new int[0];
|
||||||
|
MiddleOfArray middleOfArray = new MiddleOfArray();
|
||||||
|
Assert.assertArrayEquals(expectedMidArray, middleOfArray.middleOfArray(array));
|
||||||
|
|
||||||
|
array = new int[] { 1, 2 };
|
||||||
|
expectedMidArray = new int[] { 1, 2 };
|
||||||
|
|
||||||
|
Assert.assertArrayEquals(expectedMidArray, middleOfArray.middleOfArray(array));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenArrayOfOddLength_whenMiddleOfArray_thenReturnMid() {
|
||||||
|
int[] array = new int[99];
|
||||||
|
for (int i = 0; i < array.length; i++) {
|
||||||
|
array[i] = i + 1;
|
||||||
|
}
|
||||||
|
int[] expectedMidArray = { 50 };
|
||||||
|
MiddleOfArray middleOfArray = new MiddleOfArray();
|
||||||
|
Assert.assertArrayEquals(expectedMidArray, middleOfArray.middleOfArray(array));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenArrayWithStartAndEnd_whenMiddleOfArray_thenReturnMid() {
|
||||||
|
int[] array = new int[100];
|
||||||
|
for (int i = 0; i < array.length; i++) {
|
||||||
|
array[i] = i + 1;
|
||||||
|
}
|
||||||
|
int[] expectedMidArray = { 58 };
|
||||||
|
MiddleOfArray middleOfArray = new MiddleOfArray();
|
||||||
|
Assert.assertArrayEquals(expectedMidArray, middleOfArray.middleOfArrayWithStartEndNaive(array, 55, 60));
|
||||||
|
|
||||||
|
expectedMidArray = new int[] { 58, 59 };
|
||||||
|
Assert.assertArrayEquals(expectedMidArray, middleOfArray.middleOfArrayWithStartEndNaive(array, 56, 60));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenArrayWithStartAndEndOptimized_whenMiddleOfArray_thenReturnMid() {
|
||||||
|
int[] array = new int[100];
|
||||||
|
for (int i = 0; i < array.length; i++) {
|
||||||
|
array[i] = i + 1;
|
||||||
|
}
|
||||||
|
int[] expectedMidArray = { 78 };
|
||||||
|
MiddleOfArray middleOfArray = new MiddleOfArray();
|
||||||
|
Assert.assertArrayEquals(expectedMidArray, middleOfArray.middleOfArrayWithStartEnd(array, 55, 100));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenArrayWithStartAndEndBitwise_whenMiddleOfArray_thenReturnMid() {
|
||||||
|
int[] array = new int[100];
|
||||||
|
for (int i = 0; i < array.length; i++) {
|
||||||
|
array[i] = i + 1;
|
||||||
|
}
|
||||||
|
int[] expectedMidArray = { 78 };
|
||||||
|
MiddleOfArray middleOfArray = new MiddleOfArray();
|
||||||
|
Assert.assertArrayEquals(expectedMidArray, middleOfArray.middleOfArrayWithStartEndBitwise(array, 55, 100));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenArrayWithStartAndEnd_whenMedianOfArray_thenReturnMid() {
|
||||||
|
int[] array = new int[100];
|
||||||
|
for (int i = 0; i < array.length; i++) {
|
||||||
|
array[i] = i + 1;
|
||||||
|
}
|
||||||
|
int expectMedian = 50;
|
||||||
|
MiddleOfArray middleOfArray = new MiddleOfArray();
|
||||||
|
Assert.assertEquals(expectMedian, middleOfArray.medianOfArray(array, 0, 100));
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,4 +13,5 @@ This module contains articles about conversions among Collection types and array
|
||||||
- [Combining Two Lists Into a Map in Java](https://www.baeldung.com/java-combine-two-lists-into-map)
|
- [Combining Two Lists Into a Map in Java](https://www.baeldung.com/java-combine-two-lists-into-map)
|
||||||
- [Convert a List of Strings to a List of Integers](https://www.baeldung.com/java-convert-list-strings-to-integers)
|
- [Convert a List of Strings to a List of Integers](https://www.baeldung.com/java-convert-list-strings-to-integers)
|
||||||
- [Convert List to Long[] Array in Java](https://www.baeldung.com/java-convert-list-object-to-long-array)
|
- [Convert List to Long[] Array in Java](https://www.baeldung.com/java-convert-list-object-to-long-array)
|
||||||
|
- [Get the First n Elements of a List Into an Array](https://www.baeldung.com/java-take-start-elements-list-array)
|
||||||
- More articles: [[<-- prev]](../core-java-collections-conversions)
|
- More articles: [[<-- prev]](../core-java-collections-conversions)
|
||||||
|
|
|
@ -12,3 +12,4 @@ This module contains articles about the Java List collection
|
||||||
- [Get Unique Values From an ArrayList in Java](https://www.baeldung.com/java-unique-values-arraylist)
|
- [Get Unique Values From an ArrayList in Java](https://www.baeldung.com/java-unique-values-arraylist)
|
||||||
- [Converting a Java List to a Json Array](https://www.baeldung.com/java-converting-list-to-json-array)
|
- [Converting a Java List to a Json Array](https://www.baeldung.com/java-converting-list-to-json-array)
|
||||||
- [What’s the Difference Between Iterator and ListIterator?](https://www.baeldung.com/java-iterator-vs-listiterator)
|
- [What’s the Difference Between Iterator and ListIterator?](https://www.baeldung.com/java-iterator-vs-listiterator)
|
||||||
|
- [Create List of Object From Another Type Using Java 8](https://www.baeldung.com/java-generate-list-different-type)
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||||
<modelVersion>4.0.0</modelVersion>
|
<modelVersion>4.0.0</modelVersion>
|
||||||
<artifactId>core-java-collections-list-5</artifactId>
|
<artifactId>core-java-collections-list-5</artifactId>
|
||||||
<name>core-java-collections-list-5</name>
|
<name>core-java-collections-list-5</name>
|
||||||
|
|
|
@ -0,0 +1,114 @@
|
||||||
|
package com.baeldung.java.streamtoanotherlist;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
import org.assertj.core.util.Lists;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
import lombok.Getter;
|
||||||
|
|
||||||
|
@Getter
|
||||||
|
class Employee {
|
||||||
|
private final String name;
|
||||||
|
private final Set<String> hobbies = new HashSet<>();
|
||||||
|
private final String email;
|
||||||
|
private String department;
|
||||||
|
|
||||||
|
public Employee(String name, String email, Collection<String> hobbies) {
|
||||||
|
this.name = name;
|
||||||
|
this.email = email;
|
||||||
|
this.hobbies.addAll(hobbies);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class TennisPlayerCandidate {
|
||||||
|
private final String name;
|
||||||
|
private final String email;
|
||||||
|
private final Boolean confirmed = Boolean.FALSE;
|
||||||
|
|
||||||
|
public TennisPlayerCandidate(String name, String email) {
|
||||||
|
this.name = name;
|
||||||
|
this.email = email;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean equals(Object o) {
|
||||||
|
if (this == o)
|
||||||
|
return true;
|
||||||
|
if (!(o instanceof TennisPlayerCandidate))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
TennisPlayerCandidate that = (TennisPlayerCandidate) o;
|
||||||
|
|
||||||
|
if (!Objects.equals(name, that.name))
|
||||||
|
return false;
|
||||||
|
return Objects.equals(email, that.email);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public int hashCode() {
|
||||||
|
int result = name != null ? name.hashCode() : 0;
|
||||||
|
result = 31 * result + (email != null ? email.hashCode() : 0);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class CreateListOfDifferentTypeUsingStreamUnitTest {
|
||||||
|
private final static List<Employee> EMPLOYEES = Lists.newArrayList(
|
||||||
|
// @formatter:off
|
||||||
|
new Employee("Kai", "kai@company.com", Lists.newArrayList("Football", "Reading", "Chess")),
|
||||||
|
new Employee("Eric", "eric@company.com", Lists.newArrayList("Tennis", "Baseball", "Singing")),
|
||||||
|
new Employee("Saajan", "saajan@company.com", Lists.newArrayList("Tennis", "Baseball", "Singing")),
|
||||||
|
new Employee("Kevin", "kevin@company.com", Lists.newArrayList("Dancing", "Computer Games", "Tennis")),
|
||||||
|
new Employee("Amanda", "amanda@company.com", Lists.newArrayList("Painting", "Yoga", "Dancing"))
|
||||||
|
//@formatter:on
|
||||||
|
);
|
||||||
|
|
||||||
|
private final static List<TennisPlayerCandidate> EXPECTED = Lists.newArrayList(
|
||||||
|
// @formatter:off
|
||||||
|
new TennisPlayerCandidate("Eric", "eric@company.com"),
|
||||||
|
new TennisPlayerCandidate("Saajan", "saajan@company.com"),
|
||||||
|
new TennisPlayerCandidate("Kevin", "kevin@company.com")
|
||||||
|
//@formatter:on
|
||||||
|
);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void whenUsingStreamForEachFillingAnotherList_thenGetExpectedResult() {
|
||||||
|
List<TennisPlayerCandidate> result = new ArrayList<>();
|
||||||
|
EMPLOYEES.forEach(e -> {
|
||||||
|
if (e.getHobbies()
|
||||||
|
.contains("Tennis")) {
|
||||||
|
result.add(new TennisPlayerCandidate(e.getName(), e.getEmail()));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
assertEquals(EXPECTED, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void whenUsingStreamMap_thenGetExpectedResult() {
|
||||||
|
List<TennisPlayerCandidate> result = EMPLOYEES.stream()
|
||||||
|
.filter(e -> e.getHobbies()
|
||||||
|
.contains("Tennis"))
|
||||||
|
.map(e -> new TennisPlayerCandidate(e.getName(), e.getEmail()))
|
||||||
|
.collect(Collectors.toList());
|
||||||
|
assertEquals(EXPECTED, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
void whenUsingCollectorMapping_thenGetExpectedResult() {
|
||||||
|
List<TennisPlayerCandidate> result = EMPLOYEES.stream()
|
||||||
|
.filter(e -> e.getHobbies()
|
||||||
|
.contains("Tennis"))
|
||||||
|
.collect(Collectors.mapping(e -> new TennisPlayerCandidate(e.getName(), e.getEmail()), Collectors.toList()));
|
||||||
|
assertEquals(EXPECTED, result);
|
||||||
|
}
|
||||||
|
}
|
|
@ -9,4 +9,5 @@ This module contains articles about Map data structures in Java.
|
||||||
- [Collections.synchronizedMap vs. ConcurrentHashMap](https://www.baeldung.com/java-synchronizedmap-vs-concurrenthashmap)
|
- [Collections.synchronizedMap vs. ConcurrentHashMap](https://www.baeldung.com/java-synchronizedmap-vs-concurrenthashmap)
|
||||||
- [Java HashMap Load Factor](https://www.baeldung.com/java-hashmap-load-factor)
|
- [Java HashMap Load Factor](https://www.baeldung.com/java-hashmap-load-factor)
|
||||||
- [Converting Java Properties to HashMap](https://www.baeldung.com/java-convert-properties-to-hashmap)
|
- [Converting Java Properties to HashMap](https://www.baeldung.com/java-convert-properties-to-hashmap)
|
||||||
|
- [Get Values and Keys as ArrayList From a HashMap](https://www.baeldung.com/java-values-keys-arraylists-hashmap)
|
||||||
- More articles: [[<-- prev]](/core-java-modules/core-java-collections-maps-2)
|
- More articles: [[<-- prev]](/core-java-modules/core-java-collections-maps-2)
|
||||||
|
|
|
@ -0,0 +1,49 @@
|
||||||
|
package com.baeldung.map;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
public class MapClear {
|
||||||
|
public static Map returnCopyAndClearMap() {
|
||||||
|
// Create a HashMap
|
||||||
|
Map<String, Integer> scores = new HashMap<>();
|
||||||
|
Map<String, Integer> scores_copy;
|
||||||
|
|
||||||
|
// Add some key-value pairs
|
||||||
|
scores.put("Alice", 90);
|
||||||
|
scores.put("Bob", 85);
|
||||||
|
scores.put("Charlie", 95);
|
||||||
|
|
||||||
|
scores_copy = scores;
|
||||||
|
|
||||||
|
System.out.println("Before clearing: " + scores);
|
||||||
|
|
||||||
|
// Clear the map
|
||||||
|
scores.clear();
|
||||||
|
|
||||||
|
System.out.println("After clearing: " + scores);
|
||||||
|
return scores_copy;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Map returnCopyAndRewriteMap() {
|
||||||
|
// Create a HashMap
|
||||||
|
Map<String, Integer> scores = new HashMap<>();
|
||||||
|
Map<String, Integer> scores_copy;
|
||||||
|
|
||||||
|
// Add some key-value pairs
|
||||||
|
scores.put("Alice", 90);
|
||||||
|
scores.put("Bob", 85);
|
||||||
|
scores.put("Charlie", 95);
|
||||||
|
|
||||||
|
scores_copy = scores;
|
||||||
|
|
||||||
|
System.out.println("Before clearing: " + scores);
|
||||||
|
|
||||||
|
// Create a new map
|
||||||
|
scores = new HashMap<>();
|
||||||
|
|
||||||
|
System.out.println("After clearing: " + scores);
|
||||||
|
|
||||||
|
return scores_copy;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.baeldung.map;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
||||||
|
|
||||||
|
public class MapClearUnitTest {
|
||||||
|
@Test
|
||||||
|
public void givenMap_returnEntryAndClearContent() {
|
||||||
|
Map entry = MapClear.returnCopyAndClearMap();
|
||||||
|
assertTrue(entry.isEmpty());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test public void givenMap_returnEntryAndRewriteContent() {
|
||||||
|
Map entry = MapClear.returnCopyAndRewriteMap();
|
||||||
|
assertTrue(!entry.isEmpty());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
package com.baeldung.map;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
|
||||||
|
public class UsingtoStringUnitTest {
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void given_HashMapString_whenUsingtoString_thenConvertToHashMapObject() {
|
||||||
|
// Example string representation of a HashMap
|
||||||
|
String hashMapString = "{key1=value1, key2=value2, key3=value3}";
|
||||||
|
|
||||||
|
// Remove unnecessary characters
|
||||||
|
String keyValuePairs = hashMapString.replaceAll("[{}\\s]", "");
|
||||||
|
|
||||||
|
// Split into individual key-value pairs
|
||||||
|
String[] pairs = keyValuePairs.split(",");
|
||||||
|
|
||||||
|
// Create a new HashMap
|
||||||
|
HashMap<String, String> expectedHashMap = new HashMap<>();
|
||||||
|
expectedHashMap.put("key1", "value1");
|
||||||
|
expectedHashMap.put("key2", "value2");
|
||||||
|
expectedHashMap.put("key3", "value3");
|
||||||
|
|
||||||
|
HashMap<String, String> actualHashMap = new HashMap<>();
|
||||||
|
|
||||||
|
// Parse and populate the HashMap
|
||||||
|
for (String pair : pairs) {
|
||||||
|
String[] keyValue = pair.split("=");
|
||||||
|
if (keyValue.length == 2) {
|
||||||
|
actualHashMap.put(keyValue[0], keyValue[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assert that the converted HashMap matches the expected one
|
||||||
|
assertEquals(expectedHashMap, actualHashMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -4,4 +4,5 @@
|
||||||
- [A Guide to LinkedHashSet in Java](https://www.baeldung.com/java-linkedhashset)
|
- [A Guide to LinkedHashSet in Java](https://www.baeldung.com/java-linkedhashset)
|
||||||
- [Sorting a HashSet in Java](https://www.baeldung.com/java-sort-hashset)
|
- [Sorting a HashSet in Java](https://www.baeldung.com/java-sort-hashset)
|
||||||
- [How to Get First Item From a Java Set](https://www.baeldung.com/first-item-set)
|
- [How to Get First Item From a Java Set](https://www.baeldung.com/first-item-set)
|
||||||
|
- [Cartesian Product of Any Number of Sets in Java](https://www.baeldung.com/java-cartesian-product-sets)
|
||||||
- More articles: [[<-- prev]](/core-java-modules/core-java-collections-set)
|
- More articles: [[<-- prev]](/core-java-modules/core-java-collections-set)
|
||||||
|
|
|
@ -20,6 +20,23 @@
|
||||||
<version>${junit-platform.version}</version>
|
<version>${junit-platform.version}</version>
|
||||||
<scope>test</scope>
|
<scope>test</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.apache.commons</groupId>
|
||||||
|
<artifactId>commons-collections4</artifactId>
|
||||||
|
<version>4.4</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>org.testng</groupId>
|
||||||
|
<artifactId>testng</artifactId>
|
||||||
|
<version>7.7.0</version>
|
||||||
|
<scope>test</scope>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.google.guava</groupId>
|
||||||
|
<artifactId>guava</artifactId>
|
||||||
|
<version>32.1.1-jre</version>
|
||||||
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
<build>
|
<build>
|
||||||
|
|
|
@ -0,0 +1,75 @@
|
||||||
|
package com.baeldung.cartesianproduct;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
|
public class CartesianProduct {
|
||||||
|
public List<List<Object>> getCartesianProductIterative(List<List<Object>> sets) {
|
||||||
|
List<List<Object>> result = new ArrayList<>();
|
||||||
|
if(sets == null || sets.isEmpty()) {
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
int totalSets = sets.size();
|
||||||
|
int totalCombinations = 1 << totalSets;
|
||||||
|
for(int i = 0; i < totalCombinations; i++) {
|
||||||
|
List<Object> combination = new ArrayList<>();
|
||||||
|
for(int j = 0; j < totalSets; j++) {
|
||||||
|
if (((i >> j) & 1) == 1) {
|
||||||
|
combination.add(sets.get(j).get(0));
|
||||||
|
} else {
|
||||||
|
combination.add(sets.get(j).get(1));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
result.add(combination);
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<List<Object>> getCartesianProductRecursive(List<List<Object>> sets) {
|
||||||
|
List<List<Object>> result = new ArrayList<>();
|
||||||
|
getCartesianProductRecursiveHelper(sets, 0, new ArrayList<>(), result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void getCartesianProductRecursiveHelper(List<List<Object>> sets, int index, List<Object> current, List<List<Object>> result) {
|
||||||
|
if(index == sets.size()) {
|
||||||
|
result.add(new ArrayList<>(current));
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
List<Object> currentSet = sets.get(index);
|
||||||
|
for(Object element: currentSet) {
|
||||||
|
current.add(element);
|
||||||
|
getCartesianProductRecursiveHelper(sets, index+1, current, result);
|
||||||
|
current.remove(current.size() - 1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<List<Object>> getCartesianProductUsingStreams(List<List<Object>> sets) {
|
||||||
|
return cartesianProduct(sets,0).collect(Collectors.toList());
|
||||||
|
}
|
||||||
|
|
||||||
|
public Stream<List<Object>> cartesianProduct(List<List<Object>> sets, int index) {
|
||||||
|
if(index == sets.size()) {
|
||||||
|
List<Object> emptyList = new ArrayList<>();
|
||||||
|
return Stream.of(emptyList);
|
||||||
|
}
|
||||||
|
List<Object> currentSet = sets.get(index);
|
||||||
|
return currentSet.stream().flatMap(element -> cartesianProduct(sets, index+1)
|
||||||
|
.map(list -> {
|
||||||
|
List<Object> newList = new ArrayList<>(list);
|
||||||
|
newList.add(0, element); return newList;
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
public List<List<Object>> getCartesianProductUsingGuava(List<Set<Object>> sets) {
|
||||||
|
Set<List<Object>> cartesianProduct = Sets.cartesianProduct(sets);
|
||||||
|
List<List<Object>> cartesianList = new ArrayList<>(cartesianProduct);
|
||||||
|
return cartesianList;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,29 @@
|
||||||
|
package com.baeldung.indexawareset;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
public class IndexOfElementsInSet<E> {
|
||||||
|
public int getIndexUsingIterator(Set<E> set, E element) {
|
||||||
|
Iterator<E> iterator = set.iterator();
|
||||||
|
int index = 0;
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
if (element.equals(iterator.next())) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIndexUsingForEach(Set<E> set, E element) {
|
||||||
|
int index = 0;
|
||||||
|
for (E current : set) {
|
||||||
|
if (element.equals(current)) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,20 @@
|
||||||
|
package com.baeldung.indexawareset;
|
||||||
|
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
|
||||||
|
public class InsertionIndexAwareSet<E> extends LinkedHashSet<E> {
|
||||||
|
public InsertionIndexAwareSet() {
|
||||||
|
super();
|
||||||
|
}
|
||||||
|
|
||||||
|
public int getIndexOf(E element) {
|
||||||
|
int index = 0;
|
||||||
|
for (E current : this) {
|
||||||
|
if (current.equals(element)) {
|
||||||
|
return index;
|
||||||
|
}
|
||||||
|
index++;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,93 @@
|
||||||
|
package com.baeldung.cartesianproduct;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Arrays;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
public class CartesianProductUnitTest {
|
||||||
|
private CartesianProduct cp = new CartesianProduct();
|
||||||
|
List<List<Object>> sets = Arrays.asList(
|
||||||
|
Arrays.asList(10, 20),
|
||||||
|
Arrays.asList("John", "Jack"),
|
||||||
|
Arrays.asList('I', 'J')
|
||||||
|
);
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenUsingStreams_thenCalculateCartesianProduct() {
|
||||||
|
List<List<Object>> expected = Arrays.asList(
|
||||||
|
Arrays.asList(10, "John", 'I'),
|
||||||
|
Arrays.asList(10, "John", 'J'),
|
||||||
|
Arrays.asList(10, "Jack", 'I'),
|
||||||
|
Arrays.asList(10, "Jack", 'J'),
|
||||||
|
Arrays.asList(20, "John", 'I'),
|
||||||
|
Arrays.asList(20, "John", 'J'),
|
||||||
|
Arrays.asList(20, "Jack", 'I'),
|
||||||
|
Arrays.asList(20, "Jack", 'J')
|
||||||
|
);
|
||||||
|
List<List<Object>> cartesianProduct = cp.getCartesianProductUsingStreams(sets);
|
||||||
|
|
||||||
|
assertEquals(expected, cartesianProduct);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenUsingRecursion_thenCalculateCartesianProduct() {
|
||||||
|
List<List<Object>> expected = Arrays.asList(
|
||||||
|
Arrays.asList(10, "John", 'I'),
|
||||||
|
Arrays.asList(10, "John", 'J'),
|
||||||
|
Arrays.asList(10, "Jack", 'I'),
|
||||||
|
Arrays.asList(10, "Jack", 'J'),
|
||||||
|
Arrays.asList(20, "John", 'I'),
|
||||||
|
Arrays.asList(20, "John", 'J'),
|
||||||
|
Arrays.asList(20, "Jack", 'I'),
|
||||||
|
Arrays.asList(20, "Jack", 'J')
|
||||||
|
);
|
||||||
|
List<List<Object>> cartesianProduct = cp.getCartesianProductRecursive(sets);
|
||||||
|
|
||||||
|
assertEquals(expected, cartesianProduct);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenUsingIterativeApproach_thenCalculateCartesianProduct() {
|
||||||
|
List<List<Object>> expected = Arrays.asList(
|
||||||
|
Arrays.asList(20, "Jack", 'J'),
|
||||||
|
Arrays.asList(10, "Jack", 'J'),
|
||||||
|
Arrays.asList(20, "John", 'J'),
|
||||||
|
Arrays.asList(10, "John", 'J'),
|
||||||
|
Arrays.asList(20, "Jack", 'I'),
|
||||||
|
Arrays.asList(10, "Jack", 'I'),
|
||||||
|
Arrays.asList(20, "John", 'I'),
|
||||||
|
Arrays.asList(10, "John", 'I')
|
||||||
|
);
|
||||||
|
List<List<Object>> cartesianProduct = cp.getCartesianProductIterative(sets);
|
||||||
|
|
||||||
|
assertEquals(expected, cartesianProduct);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void whenUsingGuava_thenCalculateCartesianProduct() {
|
||||||
|
List<Set<Object>> sets = new ArrayList<>();
|
||||||
|
sets.add(new HashSet<>(Arrays.asList(10, 20)));
|
||||||
|
sets.add(new HashSet<>(Arrays.asList("John", "Jack")));
|
||||||
|
sets.add(new HashSet<>(Arrays.asList('I', 'J')));
|
||||||
|
|
||||||
|
List<List<Object>> expected = Arrays.asList(
|
||||||
|
Arrays.asList(20, "John", 'I'),
|
||||||
|
Arrays.asList(20, "John", 'J'),
|
||||||
|
Arrays.asList(20, "Jack", 'I'),
|
||||||
|
Arrays.asList(20, "Jack", 'J'),
|
||||||
|
Arrays.asList(10, "John", 'I'),
|
||||||
|
Arrays.asList(10, "John", 'J'),
|
||||||
|
Arrays.asList(10, "Jack", 'I'),
|
||||||
|
Arrays.asList(10, "Jack", 'J')
|
||||||
|
);
|
||||||
|
List<List<Object>> cartesianProduct = cp.getCartesianProductUsingGuava(sets);
|
||||||
|
|
||||||
|
assertEquals(expected, cartesianProduct);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,108 @@
|
||||||
|
package com.baeldung.indexawareset;
|
||||||
|
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.LinkedHashSet;
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.TreeSet;
|
||||||
|
|
||||||
|
import org.apache.commons.collections4.set.ListOrderedSet;
|
||||||
|
import org.junit.Assert;
|
||||||
|
import org.junit.Test;
|
||||||
|
|
||||||
|
public class IndexOfSetElementsUsingListUnitTest {
|
||||||
|
@Test
|
||||||
|
public void givenHashSet_whenIndexOfElement_thenGivesIndex() {
|
||||||
|
Set<Integer> set = new HashSet<>();
|
||||||
|
set.add(100);
|
||||||
|
set.add(20);
|
||||||
|
set.add(300);
|
||||||
|
set.add(0);
|
||||||
|
set.add(-1);
|
||||||
|
set.add(300);
|
||||||
|
|
||||||
|
IndexOfElementsInSet<Integer> integerIndexOfElementsInSet = new IndexOfElementsInSet<>();
|
||||||
|
int index100 = integerIndexOfElementsInSet.getIndexUsingIterator(set, 100);
|
||||||
|
Assert.assertEquals(index100, integerIndexOfElementsInSet.getIndexUsingIterator(set, 100));
|
||||||
|
|
||||||
|
Assert.assertEquals(-1, integerIndexOfElementsInSet.getIndexUsingIterator(set, 12));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenLinkedHashSet_whenIndexOfElement_thenGivesIndex() {
|
||||||
|
Set<Integer> set = new LinkedHashSet<>();
|
||||||
|
set.add(100);
|
||||||
|
set.add(20);
|
||||||
|
set.add(300);
|
||||||
|
set.add(0);
|
||||||
|
set.add(-1);
|
||||||
|
set.add(300);
|
||||||
|
|
||||||
|
IndexOfElementsInSet<Integer> integerIndexOfElementsInSet = new IndexOfElementsInSet<>();
|
||||||
|
Assert.assertEquals(0, integerIndexOfElementsInSet.getIndexUsingIterator(set, 100));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenTreeSet_whenIndexOfElement_thenGivesIndex() {
|
||||||
|
Set<Integer> set = new TreeSet<>();
|
||||||
|
set.add(100);
|
||||||
|
set.add(20);
|
||||||
|
set.add(300);
|
||||||
|
set.add(0);
|
||||||
|
set.add(-1);
|
||||||
|
set.add(300);
|
||||||
|
|
||||||
|
IndexOfElementsInSet<Integer> integerIndexOfElementsInSet = new IndexOfElementsInSet<>();
|
||||||
|
Assert.assertEquals(0, integerIndexOfElementsInSet.getIndexUsingIterator(set, -1));
|
||||||
|
Assert.assertEquals(3, integerIndexOfElementsInSet.getIndexUsingIterator(set, 100));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenIndexAwareSet_whenIndexOfElement_thenGivesIndex() {
|
||||||
|
InsertionIndexAwareSet<Integer> set = new InsertionIndexAwareSet<>();
|
||||||
|
set.add(100);
|
||||||
|
set.add(20);
|
||||||
|
set.add(300);
|
||||||
|
Assert.assertEquals(0, set.getIndexOf(100));
|
||||||
|
Assert.assertEquals(2, set.getIndexOf(300));
|
||||||
|
Assert.assertEquals(-1, set.getIndexOf(0));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenIndexAwareSetWithStrings_whenIndexOfElement_thenGivesIndex() {
|
||||||
|
InsertionIndexAwareSet<String> set = new InsertionIndexAwareSet<>();
|
||||||
|
set.add("Go");
|
||||||
|
set.add("Java");
|
||||||
|
set.add("Scala");
|
||||||
|
set.add("Python");
|
||||||
|
Assert.assertEquals(0, set.getIndexOf("Go"));
|
||||||
|
Assert.assertEquals(2, set.getIndexOf("Scala"));
|
||||||
|
Assert.assertEquals(-1, set.getIndexOf("C++"));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenListOrderedSet_whenIndexOfElement_thenGivesIndex() {
|
||||||
|
ListOrderedSet<Integer> set = new ListOrderedSet<>();
|
||||||
|
set.add(12);
|
||||||
|
set.add(0);
|
||||||
|
set.add(-1);
|
||||||
|
set.add(50);
|
||||||
|
|
||||||
|
Assert.assertEquals(0, set.indexOf(12));
|
||||||
|
Assert.assertEquals(2, set.indexOf(-1));
|
||||||
|
Assert.assertEquals(-1, set.indexOf(100));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void givenLinkedHashSet_whenIndexUsingUtilityMethod_thenReturnsIndex() {
|
||||||
|
Set<Integer> set = new LinkedHashSet<>();
|
||||||
|
set.add(100);
|
||||||
|
set.add(20);
|
||||||
|
set.add(300);
|
||||||
|
set.add(0);
|
||||||
|
set.add(-1);
|
||||||
|
set.add(300);
|
||||||
|
|
||||||
|
IndexOfElementsInSet<Integer> integerIndexOfElementsInSet = new IndexOfElementsInSet<>();
|
||||||
|
Assert.assertEquals(-1, integerIndexOfElementsInSet.getIndexUsingForEach(set, 150));
|
||||||
|
}
|
||||||
|
}
|
|
@ -4,6 +4,7 @@ import java.util.logging.Logger;
|
||||||
|
|
||||||
public class Consumer implements Runnable {
|
public class Consumer implements Runnable {
|
||||||
private static final Logger log = Logger.getLogger(Consumer.class.getCanonicalName());
|
private static final Logger log = Logger.getLogger(Consumer.class.getCanonicalName());
|
||||||
|
private boolean running = false;
|
||||||
private final DataQueue dataQueue;
|
private final DataQueue dataQueue;
|
||||||
|
|
||||||
public Consumer(DataQueue dataQueue) {
|
public Consumer(DataQueue dataQueue) {
|
||||||
|
@ -12,26 +13,36 @@ public class Consumer implements Runnable {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
running = true;
|
||||||
consume();
|
consume();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
running = false;
|
||||||
|
}
|
||||||
|
|
||||||
public void consume() {
|
public void consume() {
|
||||||
while (dataQueue.runFlag) {
|
while (running) {
|
||||||
while (dataQueue.isEmpty() && dataQueue.runFlag) {
|
|
||||||
|
if (dataQueue.isEmpty()) {
|
||||||
try {
|
try {
|
||||||
dataQueue.waitOnEmpty();
|
dataQueue.waitIsNotEmpty();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
e.printStackTrace();
|
log.severe("Error while waiting to Consume messages.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!dataQueue.runFlag) {
|
|
||||||
|
// avoid spurious wake-up
|
||||||
|
if (!running) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Message message = dataQueue.remove();
|
|
||||||
dataQueue.notifyAllForFull();
|
Message message = dataQueue.poll();
|
||||||
useMessage(message);
|
useMessage(message);
|
||||||
|
|
||||||
|
//Sleeping on random time to make it realistic
|
||||||
|
ThreadUtil.sleep((long) (Math.random() * 100));
|
||||||
}
|
}
|
||||||
log.info("Consumer Stopped");
|
log.info("Consumer Stopped");
|
||||||
}
|
}
|
||||||
|
@ -40,14 +51,7 @@ public class Consumer implements Runnable {
|
||||||
if (message != null) {
|
if (message != null) {
|
||||||
log.info(String.format("[%s] Consuming Message. Id: %d, Data: %f%n",
|
log.info(String.format("[%s] Consuming Message. Id: %d, Data: %f%n",
|
||||||
Thread.currentThread().getName(), message.getId(), message.getData()));
|
Thread.currentThread().getName(), message.getId(), message.getData()));
|
||||||
|
|
||||||
//Sleeping on random time to make it realistic
|
|
||||||
ThreadUtil.sleep((long) (message.getData() * 100));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void stop() {
|
|
||||||
dataQueue.runFlag = false;
|
|
||||||
dataQueue.notifyAllForEmpty();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,10 +6,8 @@ import java.util.Queue;
|
||||||
public class DataQueue {
|
public class DataQueue {
|
||||||
private final Queue<Message> queue = new LinkedList<>();
|
private final Queue<Message> queue = new LinkedList<>();
|
||||||
private final int maxSize;
|
private final int maxSize;
|
||||||
private final Object FULL_QUEUE = new Object();
|
private final Object IS_NOT_FULL = new Object();
|
||||||
private final Object EMPTY_QUEUE = new Object();
|
private final Object IS_NOT_EMPTY = new Object();
|
||||||
|
|
||||||
public boolean runFlag = true;
|
|
||||||
|
|
||||||
DataQueue(int maxSize) {
|
DataQueue(int maxSize) {
|
||||||
this.maxSize = maxSize;
|
this.maxSize = maxSize;
|
||||||
|
@ -23,39 +21,42 @@ public class DataQueue {
|
||||||
return queue.isEmpty();
|
return queue.isEmpty();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void waitOnFull() throws InterruptedException {
|
public void waitIsNotFull() throws InterruptedException {
|
||||||
synchronized (FULL_QUEUE) {
|
synchronized (IS_NOT_FULL) {
|
||||||
FULL_QUEUE.wait();
|
IS_NOT_FULL.wait();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void waitOnEmpty() throws InterruptedException {
|
public void waitIsNotEmpty() throws InterruptedException {
|
||||||
synchronized (EMPTY_QUEUE) {
|
synchronized (IS_NOT_EMPTY) {
|
||||||
EMPTY_QUEUE.wait();
|
IS_NOT_EMPTY.wait();
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void notifyAllForFull() {
|
|
||||||
synchronized (FULL_QUEUE) {
|
|
||||||
FULL_QUEUE.notifyAll();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public void notifyAllForEmpty() {
|
|
||||||
synchronized (EMPTY_QUEUE) {
|
|
||||||
EMPTY_QUEUE.notifyAll();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public void add(Message message) {
|
public void add(Message message) {
|
||||||
synchronized (queue) {
|
queue.add(message);
|
||||||
queue.add(message);
|
notifyIsNotEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
public Message poll() {
|
||||||
|
Message mess = queue.poll();
|
||||||
|
notifyIsNotFull();
|
||||||
|
return mess;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Integer getSize() {
|
||||||
|
return queue.size();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void notifyIsNotFull() {
|
||||||
|
synchronized (IS_NOT_FULL) {
|
||||||
|
IS_NOT_FULL.notify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Message remove() {
|
private void notifyIsNotEmpty() {
|
||||||
synchronized (queue) {
|
synchronized (IS_NOT_EMPTY) {
|
||||||
return queue.poll();
|
IS_NOT_EMPTY.notify();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,60 +1,63 @@
|
||||||
package com.baeldung.producerconsumer;
|
package com.baeldung.producerconsumer;
|
||||||
|
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
import java.util.logging.Logger;
|
import java.util.logging.Logger;
|
||||||
|
|
||||||
public class Producer implements Runnable {
|
public class Producer implements Runnable {
|
||||||
private static final Logger log = Logger.getLogger(Producer.class.getCanonicalName());
|
private static final Logger log = Logger.getLogger(Producer.class.getCanonicalName());
|
||||||
|
private static final AtomicInteger idSequence = new AtomicInteger(0);
|
||||||
|
private boolean running = false;
|
||||||
private final DataQueue dataQueue;
|
private final DataQueue dataQueue;
|
||||||
|
|
||||||
private static int idSequence = 0;
|
|
||||||
|
|
||||||
public Producer(DataQueue dataQueue) {
|
public Producer(DataQueue dataQueue) {
|
||||||
this.dataQueue = dataQueue;
|
this.dataQueue = dataQueue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
|
running = true;
|
||||||
produce();
|
produce();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void stop() {
|
||||||
|
running = false;
|
||||||
|
}
|
||||||
|
|
||||||
public void produce() {
|
public void produce() {
|
||||||
while (dataQueue.runFlag) {
|
|
||||||
while (dataQueue.isFull() && dataQueue.runFlag) {
|
while (running) {
|
||||||
|
|
||||||
|
if (dataQueue.isFull()) {
|
||||||
try {
|
try {
|
||||||
dataQueue.waitOnFull();
|
dataQueue.waitIsNotFull();
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
e.printStackTrace();
|
log.severe("Error while waiting to Produce messages.");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!dataQueue.runFlag) {
|
|
||||||
|
// avoid spurious wake-up
|
||||||
|
if (!running) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Message message = generateMessage();
|
|
||||||
dataQueue.add(message);
|
|
||||||
dataQueue.notifyAllForEmpty();
|
|
||||||
|
|
||||||
|
dataQueue.add(generateMessage());
|
||||||
|
|
||||||
|
log.info("Size of the queue is: " + dataQueue.getSize());
|
||||||
|
|
||||||
|
//Sleeping on random time to make it realistic
|
||||||
|
ThreadUtil.sleep((long) (Math.random() * 100));
|
||||||
}
|
}
|
||||||
|
|
||||||
log.info("Producer Stopped");
|
log.info("Producer Stopped");
|
||||||
}
|
}
|
||||||
|
|
||||||
private Message generateMessage() {
|
private Message generateMessage() {
|
||||||
Message message = new Message(incrementAndGetId(), Math.random());
|
Message message = new Message(idSequence.incrementAndGet(), Math.random());
|
||||||
log.info(String.format("[%s] Generated Message. Id: %d, Data: %f%n",
|
log.info(String.format("[%s] Generated Message. Id: %d, Data: %f%n",
|
||||||
Thread.currentThread().getName(), message.getId(), message.getData()));
|
Thread.currentThread().getName(), message.getId(), message.getData()));
|
||||||
|
|
||||||
//Sleeping on random time to make it realistic
|
|
||||||
ThreadUtil.sleep((long) (message.getData() * 100));
|
|
||||||
|
|
||||||
return message;
|
return message;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int incrementAndGetId() {
|
|
||||||
return ++idSequence;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void stop() {
|
|
||||||
dataQueue.runFlag = false;
|
|
||||||
dataQueue.notifyAllForFull();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,7 @@ public class ProducerConsumerDemonstrator {
|
||||||
// let threads run for two seconds
|
// let threads run for two seconds
|
||||||
sleep(2000);
|
sleep(2000);
|
||||||
|
|
||||||
// Stop threads
|
// stop threads
|
||||||
producer.stop();
|
producer.stop();
|
||||||
consumer.stop();
|
consumer.stop();
|
||||||
|
|
||||||
|
@ -36,28 +36,34 @@ public class ProducerConsumerDemonstrator {
|
||||||
|
|
||||||
public static void demoMultipleProducersAndMultipleConsumers() {
|
public static void demoMultipleProducersAndMultipleConsumers() {
|
||||||
DataQueue dataQueue = new DataQueue(MAX_QUEUE_CAPACITY);
|
DataQueue dataQueue = new DataQueue(MAX_QUEUE_CAPACITY);
|
||||||
int producerCount = 3;
|
int producerCount = 5;
|
||||||
int consumerCount = 3;
|
int consumerCount = 5;
|
||||||
List<Thread> threads = new ArrayList<>();
|
List<Thread> threads = new ArrayList<>();
|
||||||
Producer producer = new Producer(dataQueue);
|
List<Producer> producers = new ArrayList<>();
|
||||||
|
List<Consumer> consumers = new ArrayList<>();
|
||||||
|
|
||||||
for(int i = 0; i < producerCount; i++) {
|
for(int i = 0; i < producerCount; i++) {
|
||||||
|
Producer producer = new Producer(dataQueue);
|
||||||
Thread producerThread = new Thread(producer);
|
Thread producerThread = new Thread(producer);
|
||||||
producerThread.start();
|
producerThread.start();
|
||||||
threads.add(producerThread);
|
threads.add(producerThread);
|
||||||
|
producers.add(producer);
|
||||||
}
|
}
|
||||||
Consumer consumer = new Consumer(dataQueue);
|
|
||||||
for(int i = 0; i < consumerCount; i++) {
|
for(int i = 0; i < consumerCount; i++) {
|
||||||
|
Consumer consumer = new Consumer(dataQueue);
|
||||||
Thread consumerThread = new Thread(consumer);
|
Thread consumerThread = new Thread(consumer);
|
||||||
consumerThread.start();
|
consumerThread.start();
|
||||||
threads.add(consumerThread);
|
threads.add(consumerThread);
|
||||||
|
consumers.add(consumer);
|
||||||
}
|
}
|
||||||
|
|
||||||
// let threads run for two seconds
|
// let threads run for ten seconds
|
||||||
sleep(2000);
|
sleep(10000);
|
||||||
|
|
||||||
// Stop threads
|
// stop threads
|
||||||
producer.stop();
|
consumers.forEach(Consumer::stop);
|
||||||
consumer.stop();
|
producers.forEach(Producer::stop);
|
||||||
|
|
||||||
waitForAllThreadsToComplete(threads);
|
waitForAllThreadsToComplete(threads);
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,31 +7,37 @@ import java.util.concurrent.Phaser;
|
||||||
|
|
||||||
class LongRunningAction implements Runnable {
|
class LongRunningAction implements Runnable {
|
||||||
|
|
||||||
private static Logger log = LoggerFactory.getLogger(LongRunningAction.class);
|
private static final Logger log = LoggerFactory.getLogger(LongRunningAction.class);
|
||||||
private String threadName;
|
private final String threadName;
|
||||||
private Phaser ph;
|
private final Phaser ph;
|
||||||
|
|
||||||
LongRunningAction(String threadName, Phaser ph) {
|
LongRunningAction(String threadName, Phaser ph) {
|
||||||
this.threadName = threadName;
|
this.threadName = threadName;
|
||||||
this.ph = ph;
|
this.ph = ph;
|
||||||
|
|
||||||
|
this.randomWait();
|
||||||
|
|
||||||
ph.register();
|
ph.register();
|
||||||
|
log.info("Thread {} registered during phase {}", threadName, ph.getPhase());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
log.info("This is phase {}", ph.getPhase());
|
log.info("Thread {} BEFORE long running action in phase {}", threadName, ph.getPhase());
|
||||||
log.info("Thread {} before long running action", threadName);
|
ph.arriveAndAwaitAdvance();
|
||||||
|
|
||||||
|
randomWait();
|
||||||
|
|
||||||
|
log.info("Thread {} AFTER long running action in phase {}", threadName, ph.getPhase());
|
||||||
|
ph.arriveAndDeregister();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Simulating real work
|
||||||
|
private void randomWait() {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(2000);
|
Thread.sleep((long) (Math.random() * 100));
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
log.debug("Thread {} action completed and waiting for others", threadName);
|
|
||||||
ph.arriveAndAwaitAdvance();
|
|
||||||
log.debug("Thread {} proceeding in phase {}", threadName, ph.getPhase());
|
|
||||||
|
|
||||||
ph.arriveAndDeregister();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -7,8 +7,6 @@ import org.junit.runners.MethodSorters;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
import java.util.concurrent.ExecutorService;
|
|
||||||
import java.util.concurrent.Executors;
|
|
||||||
import java.util.concurrent.Phaser;
|
import java.util.concurrent.Phaser;
|
||||||
|
|
||||||
import static junit.framework.TestCase.assertEquals;
|
import static junit.framework.TestCase.assertEquals;
|
||||||
|
@ -16,38 +14,32 @@ import static junit.framework.TestCase.assertEquals;
|
||||||
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
@FixMethodOrder(MethodSorters.NAME_ASCENDING)
|
||||||
public class PhaserUnitTest {
|
public class PhaserUnitTest {
|
||||||
|
|
||||||
private static Logger log = LoggerFactory.getLogger(PhaserUnitTest.class);
|
private static final Logger log = LoggerFactory.getLogger(PhaserUnitTest.class);
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void givenPhaser_whenCoordinateWorksBetweenThreads_thenShouldCoordinateBetweenMultiplePhases() {
|
public void givenPhaser_whenCoordinateWorksBetweenThreads_thenShouldCoordinateBetweenMultiplePhases() throws InterruptedException {
|
||||||
//given
|
|
||||||
ExecutorService executorService = Executors.newCachedThreadPool();
|
|
||||||
Phaser ph = new Phaser(1);
|
Phaser ph = new Phaser(1);
|
||||||
assertEquals(0, ph.getPhase());
|
assertEquals(0, ph.getPhase());
|
||||||
|
|
||||||
//when
|
new Thread(new LongRunningAction("thread-1", ph)).start();
|
||||||
executorService.submit(new LongRunningAction("thread-1", ph));
|
new Thread(new LongRunningAction("thread-2", ph)).start();
|
||||||
executorService.submit(new LongRunningAction("thread-2", ph));
|
new Thread(new LongRunningAction("thread-3", ph)).start();
|
||||||
executorService.submit(new LongRunningAction("thread-3", ph));
|
|
||||||
|
|
||||||
//then
|
log.info("Thread {} waiting for others", Thread.currentThread().getName());
|
||||||
log.debug("Thread {} waiting for others", Thread.currentThread().getName());
|
|
||||||
ph.arriveAndAwaitAdvance();
|
ph.arriveAndAwaitAdvance();
|
||||||
log.debug("Thread {} proceeding in phase {}", Thread.currentThread().getName(), ph.getPhase());
|
log.info("Thread {} proceeding in phase {}", Thread.currentThread().getName(), ph.getPhase());
|
||||||
|
|
||||||
assertEquals(1, ph.getPhase());
|
assertEquals(1, ph.getPhase());
|
||||||
|
|
||||||
//and
|
new Thread(new LongRunningAction("thread-4", ph)).start();
|
||||||
executorService.submit(new LongRunningAction("thread-4", ph));
|
new Thread(new LongRunningAction("thread-5", ph)).start();
|
||||||
executorService.submit(new LongRunningAction("thread-5", ph));
|
|
||||||
|
|
||||||
log.debug("Thread {} waiting for others", Thread.currentThread().getName());
|
log.info("Thread {} waiting for new phase", Thread.currentThread().getName());
|
||||||
ph.arriveAndAwaitAdvance();
|
ph.arriveAndAwaitAdvance();
|
||||||
log.debug("Thread {} proceeding in phase {}", Thread.currentThread().getName(), ph.getPhase());
|
log.info("Thread {} proceeding in phase {}", Thread.currentThread().getName(), ph.getPhase());
|
||||||
|
|
||||||
assertEquals(2, ph.getPhase());
|
assertEquals(2, ph.getPhase());
|
||||||
|
|
||||||
|
|
||||||
ph.arriveAndDeregister();
|
ph.arriveAndDeregister();
|
||||||
|
Thread.sleep(1000);
|
||||||
|
assertEquals(true, ph.isTerminated());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,4 +11,5 @@ This module contains articles about basic Java concurrency
|
||||||
- [Runnable vs. Callable in Java](https://www.baeldung.com/java-runnable-callable)
|
- [Runnable vs. Callable in Java](https://www.baeldung.com/java-runnable-callable)
|
||||||
- [What Is Thread-Safety and How to Achieve It?](https://www.baeldung.com/java-thread-safety)
|
- [What Is Thread-Safety and How to Achieve It?](https://www.baeldung.com/java-thread-safety)
|
||||||
- [How to Get Notified When a Task Completes in Java Executors](https://www.baeldung.com/java-executors-task-completed-notification)
|
- [How to Get Notified When a Task Completes in Java Executors](https://www.baeldung.com/java-executors-task-completed-notification)
|
||||||
|
- [Difference Between Future, CompletableFuture, and Rxjava’s Observable](https://www.baeldung.com/java-future-completablefuture-rxjavas-observable)
|
||||||
- [[Next -->]](/core-java-modules/core-java-concurrency-basic-2)
|
- [[Next -->]](/core-java-modules/core-java-concurrency-basic-2)
|
||||||
|
|
|
@ -0,0 +1,73 @@
|
||||||
|
package com.baeldung.hashtableandconcurrenthashmap;
|
||||||
|
|
||||||
|
import org.openjdk.jmh.annotations.*;
|
||||||
|
import org.openjdk.jmh.infra.Blackhole;
|
||||||
|
import org.openjdk.jmh.runner.Runner;
|
||||||
|
import org.openjdk.jmh.runner.options.Options;
|
||||||
|
import org.openjdk.jmh.runner.options.OptionsBuilder;
|
||||||
|
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@BenchmarkMode(Mode.AverageTime)
|
||||||
|
@OutputTimeUnit(TimeUnit.MILLISECONDS)
|
||||||
|
@State(Scope.Benchmark)
|
||||||
|
@Fork(value = 1)
|
||||||
|
@Warmup(iterations = 3)
|
||||||
|
@Measurement(iterations = 5)
|
||||||
|
@Threads(10) // 10 threads for the test
|
||||||
|
public class BenchMarkRunner {
|
||||||
|
private Hashtable<String, Integer> hashTable;
|
||||||
|
private ConcurrentHashMap<String, Integer> concurrentHashMap;
|
||||||
|
|
||||||
|
@Setup(Level.Trial)
|
||||||
|
public void setup() {
|
||||||
|
hashTable = new Hashtable<>();
|
||||||
|
concurrentHashMap = new ConcurrentHashMap<>();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
@Group("hashtable")
|
||||||
|
public void benchmarkHashtablePut() {
|
||||||
|
for (int i = 0; i < 10000; i++) {
|
||||||
|
hashTable.put(String.valueOf(i), i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
@Group("hashtable")
|
||||||
|
public void benchmarkHashtableGet(Blackhole blackhole) {
|
||||||
|
for (int i = 0; i < 10000; i++) {
|
||||||
|
Integer value = hashTable.get(String.valueOf(i));
|
||||||
|
blackhole.consume(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
@Group("concurrentHashMap")
|
||||||
|
public void benchmarkConcurrentHashMapPut() {
|
||||||
|
for (int i = 0; i < 10000; i++) {
|
||||||
|
concurrentHashMap.put(String.valueOf(i), i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Benchmark
|
||||||
|
@Group("concurrentHashMap")
|
||||||
|
public void benchmarkConcurrentHashMapGet(Blackhole blackhole) {
|
||||||
|
for (int i = 0; i < 10000; i++) {
|
||||||
|
Integer value = concurrentHashMap.get(String.valueOf(i));
|
||||||
|
blackhole.consume(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void main(String[] args) throws Exception {
|
||||||
|
Options options = new OptionsBuilder()
|
||||||
|
.include(BenchMarkRunner.class.getSimpleName())
|
||||||
|
.shouldFailOnError(true)
|
||||||
|
.shouldDoGC(true)
|
||||||
|
.jvmArgs("-server")
|
||||||
|
.build();
|
||||||
|
new Runner(options).run();
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,62 @@
|
||||||
|
package com.baeldung.hashtableandconcurrenthashmap;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import java.util.ConcurrentModificationException;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.concurrent.ConcurrentHashMap;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertFalse;
|
||||||
|
public class ConcurrentHashMapUnitTest {
|
||||||
|
@Test
|
||||||
|
public void givenEmptyConcurrentHashMap_whenValuesAreAdded_thenValuesCanBeRetrieved() {
|
||||||
|
ConcurrentHashMap<String, String> concurrentHashMap = new ConcurrentHashMap<>();
|
||||||
|
concurrentHashMap.put("Key1", "1");
|
||||||
|
concurrentHashMap.put("Key2", "2");
|
||||||
|
concurrentHashMap.putIfAbsent("Key3", "3");
|
||||||
|
String value = concurrentHashMap.get("Key2");
|
||||||
|
|
||||||
|
assertEquals("1", concurrentHashMap.get("Key1"));
|
||||||
|
assertEquals("2", value);
|
||||||
|
assertEquals("3", concurrentHashMap.get("Key3"));
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void givenPopulatedConcurrentHashMap_whenModifiedDuringIteration_thenShouldNotThrowConcurrentModificationException() throws InterruptedException {
|
||||||
|
ConcurrentHashMap<String, Integer> concurrentHashMap = new ConcurrentHashMap<>();
|
||||||
|
concurrentHashMap.put("Key1", 1);
|
||||||
|
concurrentHashMap.put("Key2", 2);
|
||||||
|
concurrentHashMap.put("Key3", 3);
|
||||||
|
AtomicBoolean exceptionCaught = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
Thread iteratorThread = new Thread(() -> {
|
||||||
|
Iterator<String> it = concurrentHashMap.keySet().iterator();
|
||||||
|
try {
|
||||||
|
while (it.hasNext()) {
|
||||||
|
it.next();
|
||||||
|
Thread.sleep(100);
|
||||||
|
}
|
||||||
|
} catch (ConcurrentModificationException e) {
|
||||||
|
exceptionCaught.set(true);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Thread modifierThread = new Thread(() -> {
|
||||||
|
try {
|
||||||
|
Thread.sleep(50);
|
||||||
|
concurrentHashMap.put("Key4", 4);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
iteratorThread.start();
|
||||||
|
modifierThread.start();
|
||||||
|
|
||||||
|
iteratorThread.join();
|
||||||
|
modifierThread.join();
|
||||||
|
|
||||||
|
assertFalse(exceptionCaught.get());
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,63 @@
|
||||||
|
package com.baeldung.hashtableandconcurrenthashmap;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import java.util.ConcurrentModificationException;
|
||||||
|
import java.util.Hashtable;
|
||||||
|
import java.util.Iterator;
|
||||||
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
|
|
||||||
|
import static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertTrue;
|
||||||
|
public class HashtableUnitTest {
|
||||||
|
@Test
|
||||||
|
public void givenEmptyHashtable_whenValuesAreAdded_thenValuesCanBeRetrieved() {
|
||||||
|
Hashtable<String, String> hashtable = new Hashtable<>();
|
||||||
|
hashtable.put("Key1", "1");
|
||||||
|
hashtable.put("Key2", "2");
|
||||||
|
hashtable.putIfAbsent("Key3", "3");
|
||||||
|
String value = hashtable.get("Key2");
|
||||||
|
|
||||||
|
assertEquals("1", hashtable.get("Key1"));
|
||||||
|
assertEquals("2", value);
|
||||||
|
assertEquals("3", hashtable.get("Key3"));
|
||||||
|
}
|
||||||
|
@Test
|
||||||
|
public void givenPopulatedHashtable_whenModifiedDuringIteration_thenShouldThrowConcurrentModificationException() throws InterruptedException {
|
||||||
|
Hashtable<String, Integer> hashtable = new Hashtable<>();
|
||||||
|
hashtable.put("Key1", 1);
|
||||||
|
hashtable.put("Key2", 2);
|
||||||
|
hashtable.put("Key3", 3);
|
||||||
|
AtomicBoolean exceptionCaught = new AtomicBoolean(false);
|
||||||
|
|
||||||
|
Thread iteratorThread = new Thread(() -> {
|
||||||
|
Iterator<String> it = hashtable.keySet().iterator();
|
||||||
|
try {
|
||||||
|
while (it.hasNext()) {
|
||||||
|
it.next();
|
||||||
|
Thread.sleep(100);
|
||||||
|
}
|
||||||
|
} catch (ConcurrentModificationException e) {
|
||||||
|
exceptionCaught.set(true);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Thread modifierThread = new Thread(() -> {
|
||||||
|
try {
|
||||||
|
Thread.sleep(50);
|
||||||
|
hashtable.put("Key4", 4);
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
e.printStackTrace();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
iteratorThread.start();
|
||||||
|
modifierThread.start();
|
||||||
|
|
||||||
|
iteratorThread.join();
|
||||||
|
modifierThread.join();
|
||||||
|
|
||||||
|
assertTrue(exceptionCaught.get());
|
||||||
|
}
|
||||||
|
}
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue