Bael 5481 java httpclient post (#12118)

* BAEL-5481: Create new module

* BAEL-5481: Sync and async example

* BAEL-5481: Concurrent example

* BAEL-5481: Concurrent example

* BAEL-5481: JSON body example

* BAEL-5481: Form data example

* BAEL-5481: File upload example

* BAEL-5481: PR comments + Jenkins

* BAEL-5481: Update aftifact ID

* BAEL-5481: Spaces
This commit is contained in:
Daniel Strmecki 2022-05-11 09:57:02 +02:00 committed by GitHub
parent fe96f9747f
commit f24b9af096
6 changed files with 387 additions and 0 deletions

View File

@ -0,0 +1,6 @@
## Java HttpClient
This module contains articles about Java HttpClient
### Relevant articles
- TODO

View File

@ -0,0 +1,58 @@
<?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-httpclient</artifactId>
<version>0.1.0-SNAPSHOT</version>
<name>core-java-httpclient</name>
<packaging>jar</packaging>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../../pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>org.mock-server</groupId>
<artifactId>mockserver-netty</artifactId>
<version>${mockserver.version}</version>
</dependency>
<dependency>
<groupId>org.mock-server</groupId>
<artifactId>mockserver-client-java</artifactId>
<version>${mockserver.version}</version>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<version>${assertj.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler-plugin.version}</version>
<configuration>
<source>${maven.compiler.source.version}</source>
<target>${maven.compiler.target.version}</target>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<maven.compiler.source.version>11</maven.compiler.source.version>
<maven.compiler.target.version>11</maven.compiler.target.version>
<assertj.version>3.22.0</assertj.version>
<mockserver.version>5.11.2</mockserver.version>
</properties>
</project>

View File

@ -0,0 +1,162 @@
package com.baeldung.httpclient;
import java.io.IOException;
import java.net.Authenticator;
import java.net.PasswordAuthentication;
import java.net.URI;
import java.net.URLEncoder;
import java.net.http.HttpClient;
import java.net.http.HttpRequest;
import java.net.http.HttpResponse;
import java.nio.charset.StandardCharsets;
import java.nio.file.Path;
import java.util.Base64;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
public class HttpClientPost {
public static HttpResponse<String> sendSynchronousPost(String serviceUrl) throws IOException, InterruptedException {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(serviceUrl))
.POST(HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> response = client
.send(request, HttpResponse.BodyHandlers.ofString());
return response;
}
public static CompletableFuture<HttpResponse<String>> sendAsynchronousPost(String serviceUrl) {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(serviceUrl))
.POST(HttpRequest.BodyPublishers.noBody())
.build();
CompletableFuture<HttpResponse<String>> futureResponse = client
.sendAsync(request, HttpResponse.BodyHandlers.ofString());
return futureResponse;
}
public static List<CompletableFuture<HttpResponse<String>>> sendConcurrentPost(List<String> serviceUrls) {
HttpClient client = HttpClient.newHttpClient();
List<CompletableFuture<HttpResponse<String>>> completableFutures = serviceUrls.stream()
.map(URI::create)
.map(HttpRequest::newBuilder)
.map(builder -> builder.POST(HttpRequest.BodyPublishers.noBody()))
.map(HttpRequest.Builder::build)
.map(request -> client.sendAsync(request, HttpResponse.BodyHandlers.ofString()))
.collect(Collectors.toList());
return completableFutures;
}
public static HttpResponse<String> sendPostWithAuthHeader(String serviceUrl) throws IOException, InterruptedException {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(serviceUrl))
.POST(HttpRequest.BodyPublishers.noBody())
.header("Authorization", "Basic " + Base64.getEncoder()
.encodeToString(("baeldung:123456").getBytes()))
.build();
HttpResponse<String> response = client
.send(request, HttpResponse.BodyHandlers.ofString());
return response;
}
public static HttpResponse<String> sendPostWithAuthClient(String serviceUrl) throws IOException, InterruptedException {
HttpClient client = HttpClient.newBuilder()
.authenticator(new Authenticator() {
@Override
protected PasswordAuthentication getPasswordAuthentication() {
return new PasswordAuthentication(
"baeldung",
"123456".toCharArray());
}
})
.build();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(serviceUrl))
.POST(HttpRequest.BodyPublishers.noBody())
.build();
HttpResponse<String> response = client
.send(request, HttpResponse.BodyHandlers.ofString());
return response;
}
public static HttpResponse<String> sendPostWithJsonBody(String serviceUrl) throws IOException, InterruptedException {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(serviceUrl))
.POST(HttpRequest.BodyPublishers.ofString("{\"action\":\"hello\"}"))
.build();
HttpResponse<String> response = client
.send(request, HttpResponse.BodyHandlers.ofString());
return response;
}
public static HttpResponse<String> sendPostWithFormData(String serviceUrl) throws IOException, InterruptedException {
HttpClient client = HttpClient.newHttpClient();
Map<String, String> formData = new HashMap<>();
formData.put("username", "baeldung");
formData.put("message", "hello");
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(serviceUrl))
.POST(HttpRequest.BodyPublishers.ofString(getFormDataAsString(formData)))
.build();
HttpResponse<String> response = client
.send(request, HttpResponse.BodyHandlers.ofString());
return response;
}
public static HttpResponse<String> sendPostWithFileData(String serviceUrl, Path file) throws IOException, InterruptedException {
HttpClient client = HttpClient.newHttpClient();
HttpRequest request = HttpRequest.newBuilder()
.uri(URI.create(serviceUrl))
.POST(HttpRequest.BodyPublishers.ofFile(file))
.build();
HttpResponse<String> response = client
.send(request, HttpResponse.BodyHandlers.ofString());
return response;
}
private static String getFormDataAsString(Map<String, String> formData) {
StringBuilder formBodyBuilder = new StringBuilder();
for (Map.Entry<String, String> singleEntry : formData.entrySet()) {
if (formBodyBuilder.length() > 0) {
formBodyBuilder.append("&");
}
formBodyBuilder.append(URLEncoder.encode(singleEntry.getKey(), StandardCharsets.UTF_8));
formBodyBuilder.append("=");
formBodyBuilder.append(URLEncoder.encode(singleEntry.getValue(), StandardCharsets.UTF_8));
}
return formBodyBuilder.toString();
}
}

View File

@ -0,0 +1,99 @@
package com.baeldung.httpclient;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import java.io.IOException;
import java.net.http.HttpResponse;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import java.util.stream.Collectors;
import static org.assertj.core.api.Assertions.*;
class HttpClientPostUnitTest extends PostRequestMockServer {
@Test
void givenSyncPostRequest_whenServerIsAvailable_thenOkStatusIsReceived() throws IOException, InterruptedException {
HttpResponse<String> response = HttpClientPost.sendSynchronousPost(serviceUrl);
assertThat(response.statusCode()).isEqualTo(200);
assertThat(response.body()).isEqualTo("{\"message\":\"ok\"}");
}
@Test
void givenAsyncPostRequest_whenServerIsAvailable_thenOkStatusIsReceived() throws ExecutionException, InterruptedException {
CompletableFuture<HttpResponse<String>> futureResponse = HttpClientPost.sendAsynchronousPost(serviceUrl);
HttpResponse<String> response = futureResponse.get();
assertThat(response.statusCode()).isEqualTo(200);
assertThat(response.body()).isEqualTo("{\"message\":\"ok\"}");
}
@Test
void givenConcurrentPostRequests_whenServerIsAvailable_thenOkStatusIsReceived() throws ExecutionException, InterruptedException {
List<CompletableFuture<HttpResponse<String>>> completableFutures = HttpClientPost
.sendConcurrentPost(List.of(serviceUrl, serviceUrl));
CompletableFuture<List<HttpResponse<String>>> combinedFutures = CompletableFuture
.allOf(completableFutures.toArray(new CompletableFuture[0]))
.thenApply(future ->
completableFutures.stream()
.map(CompletableFuture::join)
.collect(Collectors.toList()));
List<HttpResponse<String>> responses = combinedFutures.get();
responses.forEach((response) -> {
assertThat(response.statusCode()).isEqualTo(200);
assertThat(response.body()).isEqualTo("{\"message\":\"ok\"}");
});
}
@Test
void givenPostRequestWithAuthClient_whenServerIsAvailable_thenOkStatusIsReceived() throws IOException, InterruptedException {
HttpResponse<String> response = HttpClientPost.sendPostWithAuthClient(serviceUrl);
assertThat(response.statusCode()).isEqualTo(200);
assertThat(response.body()).isEqualTo("{\"message\":\"ok\"}");
}
@Test
void givenPostRequestWithAuthHeader_whenServerIsAvailable_thenOkStatusIsReceived() throws IOException, InterruptedException {
HttpResponse<String> response = HttpClientPost.sendPostWithAuthHeader(serviceUrl);
assertThat(response.statusCode()).isEqualTo(200);
assertThat(response.body()).isEqualTo("{\"message\":\"ok\"}");
}
@Test
void givenPostRequestWithJsonBody_whenServerIsAvailable_thenOkStatusIsReceived() throws IOException, InterruptedException {
HttpResponse<String> response = HttpClientPost.sendPostWithJsonBody(serviceUrl);
assertThat(response.statusCode()).isEqualTo(200);
assertThat(response.body()).isEqualTo("{\"message\":\"ok\"}");
}
@Test
void givenPostRequestWithFormData_whenServerIsAvailable_thenOkStatusIsReceived() throws IOException, InterruptedException {
HttpResponse<String> response = HttpClientPost.sendPostWithFormData(serviceUrl);
assertThat(response.statusCode()).isEqualTo(200);
assertThat(response.body()).isEqualTo("{\"message\":\"ok\"}");
}
@Test
void givenPostRequestWithFileData_whenServerIsAvailable_thenOkStatusIsReceived(@TempDir Path tempDir) throws IOException, InterruptedException {
Path file = tempDir.resolve("temp.txt");
List<String> lines = Arrays.asList("1", "2", "3");
Files.write(file, lines);
HttpResponse<String> response = HttpClientPost.sendPostWithFileData(serviceUrl, file);
assertThat(response.statusCode()).isEqualTo(200);
assertThat(response.body()).isEqualTo("{\"message\":\"ok\"}");
}
}

View File

@ -0,0 +1,61 @@
package com.baeldung.httpclient;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.mockserver.client.MockServerClient;
import org.mockserver.integration.ClientAndServer;
import org.mockserver.model.HttpStatusCode;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.URISyntaxException;
import static org.mockserver.integration.ClientAndServer.startClientAndServer;
import static org.mockserver.model.HttpRequest.request;
import static org.mockserver.model.HttpResponse.response;
public abstract class PostRequestMockServer {
public static ClientAndServer mockServer;
public static String serviceUrl;
private static int serverPort;
public static final String SERVER_ADDRESS = "127.0.0.1";
public static final String PATH = "/test1";
public static final String METHOD = "POST";
@BeforeAll
static void startServer() throws IOException, URISyntaxException {
serverPort = getFreePort();
serviceUrl = "http://" + SERVER_ADDRESS + ":" + serverPort + PATH;
mockServer = startClientAndServer(serverPort);
mockBasicPostRequest();
}
@AfterAll
static void stopServer() {
mockServer.stop();
}
private static void mockBasicPostRequest() {
new MockServerClient(SERVER_ADDRESS, serverPort)
.when(
request()
.withPath(PATH)
.withMethod(METHOD)
)
.respond(
response()
.withStatusCode(HttpStatusCode.OK_200.code())
.withBody("{\"message\":\"ok\"}")
);
}
private static int getFreePort () throws IOException {
try (ServerSocket serverSocket = new ServerSocket(0)) {
return serverSocket.getLocalPort();
}
}
}

View File

@ -1318,6 +1318,7 @@
<module>core-java-modules/core-java-networking-3</module>
<module>core-java-modules/multimodulemavenproject</module>
<module>core-java-modules/core-java-strings</module>
<module>core-java-modules/core-java-httpclient</module>
<module>ddd-modules</module>
<module>docker</module>
<module>apache-httpclient-2</module>