Repository: iluwatar/java-design-patterns
Issue: Java 11 support: HttpClient
Labels: type: enhancement
info: good first issue
epic: dependencies
epic: architecture
type: refactoring

This task is part of the Java 11 transition plan https://github.com/iluwatar/java-design-patterns/wiki/16.-Java-11-Transition

Patterns Aggregator Microservices and API Gateway are currently using Apache HttpClient in their implementation. Java 11 provides its own HttpClient and we should switch to that instead to get rid of unnecessary external dependencies.

Links:
https://winterbe.com/posts/2018/09/24/java-11-tutorial/#http-client


Issue comments:
I'd be interested in looking into this, can I go ahead and try?
Ok @oconnelc 
Which version of JDK should I compile against? Should I use Oracle or Openjdk? 
We have just switched to openjdk11

Pull request review comments:

Patch that resolved the issue:
diff --git a/aggregator-microservices/aggregator-service/pom.xml b/aggregator-microservices/aggregator-service/pom.xml
index 6ad8c3c8c5a4..f1ea05a6ec4d 100644
--- a/aggregator-microservices/aggregator-service/pom.xml
+++ b/aggregator-microservices/aggregator-service/pom.xml
@@ -53,10 +53,6 @@
             <artifactId>mockito-core</artifactId>
             <scope>test</scope>
         </dependency>
-        <dependency>
-            <groupId>org.apache.httpcomponents</groupId>
-            <artifactId>httpclient</artifactId>
-        </dependency>
     </dependencies>
 
     <build>
diff --git a/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInformationClientImpl.java b/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInformationClientImpl.java
index 131fbf8695cd..c731a695d2a3 100644
--- a/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInformationClientImpl.java
+++ b/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInformationClientImpl.java
@@ -22,18 +22,16 @@
  */
 package com.iluwatar.aggregator.microservices;
 
-import org.apache.http.client.ClientProtocolException;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClients;
-import org.apache.http.util.EntityUtils;
+import java.io.IOException;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Component;
 
-import java.io.IOException;
-
 /**
  * An adapter to communicate with information micro-service.
  */
@@ -45,16 +43,17 @@ public class ProductInformationClientImpl implements ProductInformationClient {
   @Override
   public String getProductTitle() {
     String response = null;
-    try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
-      HttpGet httpGet = new HttpGet("http://localhost:51515/information");
-      try (CloseableHttpResponse httpResponse = httpClient.execute(httpGet)) {
-        response = EntityUtils.toString(httpResponse.getEntity());
-      }
-    } catch (ClientProtocolException cpe) {
-      LOGGER.error("ClientProtocolException Occured", cpe);
+    HttpRequest request = 
+    		HttpRequest.newBuilder().GET().uri(URI.create("http://localhost:51515/information")).build();
+    HttpClient client = HttpClient.newHttpClient();
+    try {
+		HttpResponse<String> httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString());
+		response = httpResponse.body();
     } catch (IOException ioe) {
-      LOGGER.error("IOException Occurred", ioe);
-    }
+    	LOGGER.error("IOException Occurred", ioe);
+	} catch (InterruptedException ie) {
+		LOGGER.error("InterruptedException Occurred", ie);
+	}
     return response;
   }
 }
diff --git a/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInventoryClientImpl.java b/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInventoryClientImpl.java
index 780dccb78e20..7e855fffe149 100644
--- a/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInventoryClientImpl.java
+++ b/aggregator-microservices/aggregator-service/src/main/java/com/iluwatar/aggregator/microservices/ProductInventoryClientImpl.java
@@ -22,39 +22,39 @@
  */
 package com.iluwatar.aggregator.microservices;
 
-import org.apache.http.client.ClientProtocolException;
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClients;
-import org.apache.http.util.EntityUtils;
+import java.io.IOException;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.springframework.stereotype.Component;
 
-import java.io.IOException;
-
 /**
  * An adapter to communicate with inventory micro-service.
  */
 @Component
 public class ProductInventoryClientImpl implements ProductInventoryClient {
 
-  private static final Logger LOGGER = LoggerFactory.getLogger(ProductInventoryClientImpl.class);
+	private static final Logger LOGGER = LoggerFactory.getLogger(ProductInventoryClientImpl.class);
 
-  @Override
-  public int getProductInventories() {
-    String response = "0";
-    try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
-      HttpGet httpGet = new HttpGet("http://localhost:51516/inventories");
-      try (CloseableHttpResponse httpResponse = httpClient.execute(httpGet)) {
-        response = EntityUtils.toString(httpResponse.getEntity());
-      }
-    } catch (ClientProtocolException cpe) {
-      LOGGER.error("ClientProtocolException Occured", cpe);
-    } catch (IOException ioe) {
-      LOGGER.error("IOException Occurred", ioe);
-    }
-    return Integer.parseInt(response);
-  }
+	@Override
+	public int getProductInventories() {
+		String response = "0";
+		
+		HttpRequest request = 
+				HttpRequest.newBuilder().GET().uri(URI.create("http://localhost:51516/inventories")).build();
+		HttpClient client = HttpClient.newHttpClient();
+		try {
+			HttpResponse<String> httpResponse = client.send(request, HttpResponse.BodyHandlers.ofString());
+			response = httpResponse.body();
+		} catch (IOException ioe) {
+			LOGGER.error("IOException Occurred", ioe);
+		} catch (InterruptedException ie) {
+			LOGGER.error("InterruptedException Occurred", ie);
+		}
+		return Integer.parseInt(response);
+	}
 }
diff --git a/api-gateway/api-gateway-service/pom.xml b/api-gateway/api-gateway-service/pom.xml
index 44a8bde37923..fdea5c2a4993 100644
--- a/api-gateway/api-gateway-service/pom.xml
+++ b/api-gateway/api-gateway-service/pom.xml
@@ -39,10 +39,6 @@
       <groupId>org.springframework</groupId>
       <artifactId>spring-webmvc</artifactId>
     </dependency>
-    <dependency>
-      <groupId>org.apache.httpcomponents</groupId>
-      <artifactId>httpclient</artifactId>
-    </dependency>
     <dependency>
       <groupId>org.springframework.boot</groupId>
       <artifactId>spring-boot-starter-web</artifactId>
diff --git a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ImageClientImpl.java b/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ImageClientImpl.java
index ebabfe839b69..63dd270e965f 100644
--- a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ImageClientImpl.java
+++ b/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/ImageClientImpl.java
@@ -22,35 +22,42 @@
  */
 package com.iluwatar.api.gateway;
 
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClients;
-import org.apache.http.util.EntityUtils;
-import org.springframework.stereotype.Component;
-
 import java.io.IOException;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.net.http.HttpResponse.BodyHandlers;
+
+import org.springframework.stereotype.Component;
 
 /**
  * An adapter to communicate with the Image microservice
  */
 @Component
 public class ImageClientImpl implements ImageClient {
-  /**
-   * Makes a simple HTTP Get request to the Image microservice
-   * @return The path to the image
-   */
-  @Override
-  public String getImagePath() {
-    String response = null;
-    try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
-      HttpGet httpGet = new HttpGet("http://localhost:50005/image-path");
-      try (CloseableHttpResponse httpResponse = httpClient.execute(httpGet)) {
-        response = EntityUtils.toString(httpResponse.getEntity());
-      }
-    } catch (IOException e) {
-      e.printStackTrace();
-    }
-    return response;
-  }
+	/**
+	 * Makes a simple HTTP Get request to the Image microservice
+	 * @return The path to the image
+	 */
+	@Override
+	public String getImagePath() {
+		String response = null;
+
+		HttpClient httpClient = 
+				HttpClient.newHttpClient();
+		HttpRequest httpGet = 
+				HttpRequest.newBuilder().GET().uri(URI.create("http://localhost:50005/image-path")).build();
+
+		try {
+			HttpResponse<String> httpResponse = httpClient.send(httpGet, BodyHandlers.ofString());
+			response = httpResponse.body();
+		} catch (IOException e) {
+			e.printStackTrace();
+		} catch (InterruptedException e) {
+			e.printStackTrace();
+		}
+
+		return response;
+	}
 }
diff --git a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/PriceClientImpl.java b/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/PriceClientImpl.java
index 87f44761c649..e8ef38bff3b2 100644
--- a/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/PriceClientImpl.java
+++ b/api-gateway/api-gateway-service/src/main/java/com/iluwatar/api/gateway/PriceClientImpl.java
@@ -22,35 +22,43 @@
  */
 package com.iluwatar.api.gateway;
 
-import org.apache.http.client.methods.CloseableHttpResponse;
-import org.apache.http.client.methods.HttpGet;
-import org.apache.http.impl.client.CloseableHttpClient;
-import org.apache.http.impl.client.HttpClients;
-import org.apache.http.util.EntityUtils;
-import org.springframework.stereotype.Component;
-
 import java.io.IOException;
+import java.net.URI;
+import java.net.http.HttpClient;
+import java.net.http.HttpRequest;
+import java.net.http.HttpResponse;
+import java.net.http.HttpResponse.BodyHandlers;
+
+import org.springframework.stereotype.Component;
 
 /**
  * An adapter to communicate with the Price microservice
  */
 @Component
 public class PriceClientImpl implements PriceClient {
-  /**
-   * Makes a simple HTTP Get request to the Price microservice
-   * @return The price of the product
-   */
-  @Override
-  public String getPrice() {
-    String response = null;
-    try (CloseableHttpClient httpClient = HttpClients.createDefault()) {
-      HttpGet httpGet = new HttpGet("http://localhost:50006/price");
-      try (CloseableHttpResponse httpResponse = httpClient.execute(httpGet)) {
-        response = EntityUtils.toString(httpResponse.getEntity());
-      }
-    } catch (IOException e) {
-      e.printStackTrace();
-    }
-    return response;
-  }
+	/**
+	 * Makes a simple HTTP Get request to the Price microservice
+	 * @return The price of the product
+	 */
+	@Override
+	public String getPrice() {
+		
+		String response = null;
+
+		HttpClient httpClient = 
+				HttpClient.newHttpClient();
+		HttpRequest httpGet = 
+				HttpRequest.newBuilder().GET().uri(URI.create("http://localhost:50006/price")).build();
+
+		try {
+			HttpResponse<String> httpResponse = httpClient.send(httpGet, BodyHandlers.ofString());
+			response = httpResponse.body();
+		} catch (IOException e) {
+			e.printStackTrace();
+		} catch (InterruptedException e) {
+			e.printStackTrace();
+		}
+		
+		return response;
+	}
 }
diff --git a/pom.xml b/pom.xml
index 9b4672fb3b6e..80b0b3e706e8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -43,7 +43,6 @@
         <camel.version>2.24.0</camel.version>
         <guava.version>19.0</guava.version>
         <mockito.version>1.10.19</mockito.version>
-        <apache-httpcomponents.version>4.5.10</apache-httpcomponents.version>
         <htmlunit.version>2.22</htmlunit.version>
         <guice.version>4.0</guice.version>
         <mongo-java-driver.version>3.3.0</mongo-java-driver.version>
@@ -212,11 +211,6 @@
                 <artifactId>spring-webmvc</artifactId>
                 <version>${spring.version}</version>
             </dependency>
-            <dependency>
-                <groupId>org.apache.httpcomponents</groupId>
-                <artifactId>httpclient</artifactId>
-                <version>${apache-httpcomponents.version}</version>
-            </dependency>
             <dependency>
                 <groupId>com.h2database</groupId>
                 <artifactId>h2</artifactId>


Test patch: