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:
parent
fe96f9747f
commit
f24b9af096
6
core-java-modules/core-java-httpclient/README.md
Normal file
6
core-java-modules/core-java-httpclient/README.md
Normal file
@ -0,0 +1,6 @@
|
||||
## Java HttpClient
|
||||
|
||||
This module contains articles about Java HttpClient
|
||||
|
||||
### Relevant articles
|
||||
- TODO
|
58
core-java-modules/core-java-httpclient/pom.xml
Normal file
58
core-java-modules/core-java-httpclient/pom.xml
Normal 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>
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
@ -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\"}");
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
1
pom.xml
1
pom.xml
@ -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>
|
||||
|
Loading…
x
Reference in New Issue
Block a user