{{announcement.body}}
{{announcement.title}}

Java 11 HTTP Client API to Consume Restful Web Service Created Using Spring Boot

DZone 's Guide to

Java 11 HTTP Client API to Consume Restful Web Service Created Using Spring Boot

This article describes how to use Java 11 Http Client API to send HTTP GET/POST/PUT/DELETE requests.

· Java Zone ·
Free Resource

One of the features added in Java 11 is the standardized Http Client API. This article describes how to use Java 11 Http Client API to send HTTP GET/POST/PUT/DELETE requests.

This new API supports HTTP / 1.1 as well as HTTP 2. The newer version of the HTTP protocol is designed to improve the overall performance of sending requests by a client and receiving responses from the server. This is achieved by introducing several changes such as stream multiplexing, header compression and push promises.

In JDK 11, a new module is introduced as follows:

Java
 




x


 
1
module java.net.http {
2
exports java.net.http;
3
}



The package contains:

HttpClient

  • Used to send requests and receive responses. Provides Synchronous and Asynchronous request mechanisms.
  • HttpClient instance is immutable, once created you can send multiple requests with the same.
  • To send requests, first you need to create HttpClient.
  • Example:
  • Java
     




    xxxxxxxxxx
    1


     
    1
    HttpClient client = HttpClient.newBuilder().version(Version.HTTP_2).build();


  • If HTTP/2 is not supported by the server, processes the request using HTTP/1.1
  • You can use executor() for asynchronous tasks.

HttpRequest

  • Create HttpRequest instance and set the URI, request method optionally specify the body and headers.
  • HttpRequest instance is immutable and can be sent multiple times.
  • Client supports all HTTP methods. Methods available to make different requests are GET(), POST(), PUT(), DELETE(), method().
  • Example:
  • Java
     




    xxxxxxxxxx
    1


     
    1
    HttpRequest request = HttpRequest.newBuilder(URI.create(“http://localhost:8080/addDetails”))
    2
    .header("Content-Type", "application/json")
    3
        .POST(HttpRequest.BodyPublishers.ofString(inputJson)).build();
    4
     
                



HttpRequest.BodyPublisher/HttpRequest.BodyPublishers

  • BodyPublisher is used to send the request with a request body.
  • BodyPublishers are responsible for publishing the body content from a String or a File.
  • In the above example, created BodyPublisher using BodyPublishers.ofString() and passing it as an argument to POST() method.

HttpResponse

  • Once after HttpRequest is sent by the client, HttpResponse is received which includes headers and a message body, if any.
  • Example:
    Java
     




    xxxxxxxxxx
    1


     
    1
    CompletableFuture<HttpResponse<String>> response = client.sendAsync(request,HttpResponse.BodyHandlers.ofString());


  • sendAsync() is used to send the HttpRequest Asynchronously(non-blocking) and returns CompletableFuture.

HttpResponse.BodyHandler/HttpResponse.BodyHandlers

  • HttpResponse.BodyHandler determines how to handle response body. The BodyHandler is invoked once the response status code and headers are available, but before the response body bytes are received. The BodyHandler is responsible for creating the BodySubscriber.
  • HttpResponse.BodyHandlers provides factory methods for creating Body Handler. Accumulates the response bytes in memory until it is completely received, after which it is converted into the high-level java type like String.

HttpResponse.BodySubscriber

  • HttpResponse.BodySubscriber is a reactive-stream subscriber that receives streams of data with non-blocking back pressure.

Consider you have created a RESTful web service using Spring Boot. You can use Java 11 Http Client API to send the request asynchronously and to receive the response. No need to add any external library to your project.

Software Required:

  1. Eclipse
  2. JDK 11
  3. MySQL 8.0

Create RESTful web service application using Spring Boot 2.1.x with the following project structure.

productservice

1. You can refer POM.xml here:

XML


2. Mention the below in application.properties file.

Properties files
 




xxxxxxxxxx
1


 
1
spring.datasource.url= jdbc:mysql://localhost:3307/springrestdemos
2
spring.datasource.username=root
3
spring.datasource.password=root
4
spring.jpa.hibernate.ddl-auto = create
5
spring.jpa.show-sql = true
6
spring.jpa.properties.hibernate.dialect = org.hibernate.dialect.MySQL5Dialect
7
 
          



3. Create ProductBean class in com.example.productservice.business.bean package.

Java
 




xxxxxxxxxx
1


 
1
public class ProductBean {
2
    private int id;
3
    private String name;    
4
    private String description;
5
    private Double price;
6
    // getters and setters
7
    // toString()
8
}
9
 
          



4. Create ProductController class in com.example.productservice.controller package.

Java
 




xxxxxxxxxx
1
64


 
1
package com.example.productservice.controller;
2
import java.util.ArrayList;
3
import java.util.List;
4
import org.springframework.beans.factory.annotation.Autowired;
5
import org.springframework.http.HttpStatus;
6
import org.springframework.http.MediaType;
7
import org.springframework.http.ResponseEntity;
8
import org.springframework.web.bind.annotation.DeleteMapping;
9
import org.springframework.web.bind.annotation.GetMapping;
10
import org.springframework.web.bind.annotation.PathVariable;
11
import org.springframework.web.bind.annotation.PostMapping;
12
import org.springframework.web.bind.annotation.PutMapping;
13
import org.springframework.web.bind.annotation.RequestBody;
14
import org.springframework.web.bind.annotation.RestController;
15
import com.example.productservice.business.bean.ProductBean;
16
import com.example.productservice.service.ProductServiceImpl;
17
@RestController
18
public class ProductController {
19
    @Autowired
20
    private ProductServiceImpl productServiceImpl;
21
    
22
    @GetMapping(value = "product/controller/getDetails", produces = MediaType.APPLICATION_JSON_VALUE )
23
    public ResponseEntity<List<ProductBean>> getProductDetails() {
24
        List<ProductBean> listProduct = new ArrayList<ProductBean>(productServiceImpl.getAllProduct());
25
        return new ResponseEntity<List<ProductBean>>(listProduct,HttpStatus.OK);
26
    }
27
 
          
28
    @GetMapping(value="product/controller/getDetailsById/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
29
    public ResponseEntity<ProductBean> getProductDetailByEmployeeId(@PathVariable("id") int myId) {
30
        ProductBean product = productServiceImpl.getProductDetailsById(myId);
31
        if (product != null) {
32
            return new ResponseEntity<ProductBean>(product, HttpStatus.OK);
33
        } else {
34
            return new ResponseEntity<ProductBean>(HttpStatus.NOT_FOUND);
35
        }
36
    }
37
 
          
38
    @PostMapping(value="product/controller/addProduct", consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.TEXT_HTML_VALUE)
39
    public ResponseEntity<String> addProduct(@RequestBody ProductBean product) {
40
        int count=productServiceImpl.addProduct(product);
41
        return new ResponseEntity<String>("Product added successfully with id:" + count,HttpStatus.CREATED);
42
    }
43
    
44
    @PutMapping(value = "product/controller/updateProduct",consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)
45
    public ResponseEntity<ProductBean> updateProduct(@RequestBody  ProductBean product) {
46
        if (productServiceImpl.getProductDetailsById(product.getId()) == null) {
47
            ProductBean product2 = null;
48
            return new ResponseEntity<ProductBean>(product2,HttpStatus.INTERNAL_SERVER_ERROR);
49
        }
50
        ProductBean updated = productServiceImpl.updateProduct(product);
51
        return new ResponseEntity<ProductBean>(updated, HttpStatus.OK);
52
    }
53
 
          
54
    @DeleteMapping(value = "product/controller/deleteProduct/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
55
    public ResponseEntity<ProductBean> deleteProduct(@PathVariable("id") int myId) {
56
        ProductBean product2=productServiceImpl.getProductDetailsById(myId);
57
        if (productServiceImpl.getProductDetailsById(myId) == null) {
58
            return new ResponseEntity<ProductBean>(product2,HttpStatus.INTERNAL_SERVER_ERROR);
59
        }
60
        productServiceImpl.removeProduct(myId);
61
        return new ResponseEntity<ProductBean>(product2, HttpStatus.OK);
62
    }
63
}
64
 
          



5. Create ProductService Inteface in com.example.productservice.service package.


Java
 




xxxxxxxxxx
1
11


 
1
package com.example.productservice.service;
2
import java.util.Collection;
3
import com.example.productservice.business.bean.ProductBean;
4
public interface ProductService {
5
    Collection<ProductBean> getAllProduct();
6
    ProductBean getProductDetailsById(int id);
7
    Integer addProduct(ProductBean product);
8
    ProductBean updateProduct(ProductBean product);
9
    void removeProduct(int id);
10
}
11
 
          



6. Create ProductServiceImpl class in com.example.productservice.service package.

Java
 




xxxxxxxxxx
1
27


 
1
package com.example.productservice.service;
2
import java.util.Collection;
3
import org.springframework.beans.factory.annotation.Autowired;
4
import org.springframework.stereotype.Service;
5
import com.example.productservice.business.bean.ProductBean;
6
import com.example.productservice.dao.ProductDAOWrapper;
7
@Service
8
public class ProductServiceImpl implements ProductService {
9
    @Autowired
10
    private ProductDAOWrapper productDAOWrapper;
11
    public Collection<ProductBean> getAllProduct(){
12
        return productDAOWrapper.findAll();         
13
    }
14
    public ProductBean getProductDetailsById(int id){
15
        return productDAOWrapper.findOne(id);
16
    }
17
    public Integer addProduct(ProductBean product){
18
        return productDAOWrapper.saveProduct(product);
19
    }
20
    public ProductBean updateProduct (ProductBean product){
21
        return productDAOWrapper.updateProduct(product);
22
    }
23
    public void removeProduct (int id){
24
        productDAOWrapper.delete(id);
25
    }
26
}
27
 
          



7. Create ProductDAO interface in com.example.productservice.dao package.

Java
 




xxxxxxxxxx
1


 
1
package com.example.productservice.dao;
2
import org.springframework.data.jpa.repository.JpaRepository;
3
import com.example.productservice.entity.ProductEntity;
4
public interface ProductDAO extends JpaRepository<ProductEntity, Integer>
5
{
6
}
7
 
          



8. Create ProductDAOWrapper class in com.example.productservice.dao package.

Java
 




xxxxxxxxxx
1
56


 
1
package com.example.productservice.dao;
2
import java.util.ArrayList;
3
import java.util.List;
4
import org.springframework.beans.BeanUtils;
5
import org.springframework.beans.factory.annotation.Autowired;
6
import org.springframework.stereotype.Repository;
7
import com.example.productservice.business.bean.ProductBean;
8
import com.example.productservice.entity.ProductEntity;
9
@Repository
10
public class ProductDAOWrapper {
11
    @Autowired
12
    private ProductDAO dao;
13
    
14
    public List<ProductBean>findAll(){
15
        List<ProductBean> list = new ArrayList<ProductBean>(); 
16
        Iterable<ProductEntity> listEn= dao.findAll();
17
        listEn.forEach(x->{
18
            ProductBean product = new ProductBean();
19
            BeanUtils.copyProperties(x, product);
20
            list.add(product);
21
        });
22
        return list;
23
    }
24
        
25
    public ProductBean findOne(Integer id){ 
26
            ProductEntity x= dao.findById(id).get();
27
            ProductBean product =null;
28
            if(x!=null){
29
                product = new ProductBean();        
30
                BeanUtils.copyProperties(x, product);
31
                }
32
            System.out.println(x);
33
        return product;
34
    }
35
    
36
    public Integer saveProduct(ProductBean product){
37
        ProductEntity productEntityBean = new ProductEntity();
38
        BeanUtils.copyProperties(product, productEntityBean);
39
        ProductEntity en=  dao.save(productEntityBean);
40
        return en.getId();  
41
    }
42
    
43
    public ProductBean updateProduct(ProductBean product){
44
        ProductEntity productEntityBean = new ProductEntity();
45
        BeanUtils.copyProperties(product, productEntityBean);
46
        ProductEntity en=  dao.save(productEntityBean);
47
        ProductBean product2 = new ProductBean();
48
        BeanUtils.copyProperties(en,product2);
49
        return product2;    
50
    }
51
    
52
    public void delete(int id){
53
        dao.deleteById(id);
54
    }
55
}
56
 
          



9. Create ProductEntity Class in com.example.productservice.entity package.

Java
 




xxxxxxxxxx
1
18


 
1
package com.example.productservice.entity;
2
import javax.persistence.Entity;
3
import javax.persistence.GeneratedValue;
4
import javax.persistence.GenerationType;
5
import javax.persistence.Id;
6
import javax.persistence.Table;
7
@Entity
8
@Table(name="product")
9
public class ProductEntity {
10
    @Id
11
    @GeneratedValue(strategy=GenerationType.IDENTITY)
12
    private int id;
13
    private String name;    
14
    private String description;
15
    private Double price;
16
    // getters and setters
17
}
18
 
          



Run the application using clean install spring-boot:run in maven goal.

Open Browser and hit the Url as:

http://localhost:8080/emp/controller/getDetails

Create a Java Application with JDK 11 to consume the ProductService application created:

1. Add Jackson-annotations-2.7.3, Jackson-core-2.7.3, Jackson-databind-2.7.3 jar files in the module path.

2. Make the HttpClientAsyncDemo module as open.

Java
 




xxxxxxxxxx
1


 
1
open module HttpClientAsyncDemo {
2
    requires java.net.http;
3
    requires jackson.databind;
4
    requires jackson.core;
5
}
6
 
          



3. Create JSONUtils class in com.httpclientdemo.utility package. Used to convert JSON into Object and vice versa.

Java
 




xxxxxxxxxx
1
29


 
1
package com.httpclientdemo.utility;
2
import java.io.IOException;
3
import java.util.List;
4
import com.fasterxml.jackson.core.JsonParseException;
5
import com.fasterxml.jackson.core.JsonProcessingException;
6
import com.fasterxml.jackson.core.type.TypeReference;
7
import com.fasterxml.jackson.databind.JsonMappingException;
8
import com.fasterxml.jackson.databind.ObjectMapper;
9
public class JSONUtils {
10
    //convert JSON into List of Objects
11
    static public <T> List<T> convertFromJsonToList(String json, TypeReference<List<T>> var) throws JsonParseException, JsonMappingException, IOException
12
    {
13
        ObjectMapper mapper = new ObjectMapper();
14
        return mapper.readValue(json, var);
15
    }
16
    
17
    //Generic Type Safe Method – convert JSON into Object
18
    static public <T> T covertFromJsonToObject(String json, Class<T> var) throws IOException{
19
        ObjectMapper mapper = new ObjectMapper();
20
        return mapper.readValue(json, var);//Convert Json into object of Specific Type
21
    }
22
    //convert Object into JSON
23
    public static String covertFromObjectToJson(Object obj) throws JsonProcessingException{
24
        ObjectMapper mapper = new ObjectMapper();
25
        return mapper.writeValueAsString(obj);
26
    }
27
 
          
28
}
29
 
          



4. Create ProductBean class in com.httpclientdemo.business.bean package as same as ProductService application.

5. Create a main java class HttpClientAsyncDemo class in com.httpclientdemo.uiclient package.

Java
 




xxxxxxxxxx
1
110


 
1
package com.httpclientdemo.uiclient;
2
import java.io.IOException;
3
import java.net.URI;
4
import java.net.http.HttpClient;
5
import java.net.http.HttpClient.Version;
6
import java.net.http.HttpRequest;
7
import java.net.http.HttpResponse;
8
import java.net.http.HttpResponse.BodyHandlers;
9
import java.util.List;
10
import java.util.concurrent.CompletableFuture;
11
import java.util.concurrent.ExecutionException;
12
import com.fasterxml.jackson.core.JsonParseException;
13
import com.fasterxml.jackson.core.JsonProcessingException;
14
import com.fasterxml.jackson.core.type.TypeReference;
15
import com.fasterxml.jackson.databind.JsonMappingException;
16
import com.httpclientdemo.business.bean.ProductBean;
17
import com.httpclientdemo.utility.JSONUtils;
18
 
          
19
public class HttpClientAsyncDemo {
20
private static final HttpClient client = HttpClient.newBuilder().version(Version.HTTP_2).build();
21
private static final String serviceURL = "http://localhost:8080/product/controller/";
22
public static void main(String[] args) throws InterruptedException, ExecutionException, IOException{
23
 
          
24
    //getAllProducts();
25
    //getProductDetailsById();
26
    addProduct();
27
    //updateProduct();
28
    //deleteProduct();
29
}
30
//sending request to retrieve all the products available.
31
public static void getAllProducts() throws InterruptedException, ExecutionException, JsonParseException, JsonMappingException, IOException
32
{
33
    HttpRequest req = HttpRequest.newBuilder(URI.create(serviceURL+"getDetails"))
34
            .GET().build();
35
    CompletableFuture<HttpResponse<String>> response = client.sendAsync(req, BodyHandlers.ofString());
36
    response.thenAccept(res -> System.out.println(res));
37
    List<ProductBean> products = JSONUtils.convertFromJsonToList(response.get().body(), new TypeReference<List<ProductBean>>() {});
38
    products.forEach(System.out::println);
39
    response.join();
40
}
41
//sending request retrieve the product based on the productId
42
public static void getProductDetailsById() throws InterruptedException, ExecutionException, IOException
43
{
44
    HttpRequest req = HttpRequest.newBuilder(URI.create(serviceURL+"getDetailsById/1"))
45
            .GET().build();
46
    CompletableFuture<HttpResponse<String>> response = client.sendAsync(req, BodyHandlers.ofString());
47
    response.thenAccept(res -> System.out.println(res));
48
    if(response.get().statusCode() == 500)
49
        System.out.println("Product Not Avaialble");
50
    else
51
    {
52
        ProductBean bean = JSONUtils.covertFromJsonToObject(response.get().body(), ProductBean.class);
53
        System.out.println(bean);
54
    }
55
    response.join();
56
}
57
//send request to add the product details.
58
public static void addProduct() throws InterruptedException, ExecutionException, JsonProcessingException
59
{
60
    ProductBean bean = new ProductBean();
61
    bean.setName("handwash");
62
    bean.setDescription("Herbal");
63
    bean.setPrice(143.10);
64
 
          
65
    String inputJson = JSONUtils.covertFromObjectToJson(bean);
66
    
67
    HttpRequest request = HttpRequest.newBuilder(URI.create(serviceURL+"addProduct"))
68
            .header("Content-Type", "application/json")
69
            .POST(HttpRequest.BodyPublishers.ofString(inputJson)).build();
70
    CompletableFuture<HttpResponse<String>> response = client.sendAsync(request,HttpResponse.BodyHandlers.ofString());
71
    System.out.println(response.get().body());
72
}
73
//send request to update the product details.
74
public static void updateProduct() throws InterruptedException, ExecutionException, IOException
75
{
76
    ProductBean bean = new ProductBean();
77
    bean.setId(1);
78
    bean.setName("Hand Wash");
79
    bean.setDescription("Herbal Prodcuct by XYZ company");
80
    bean.setPrice(198.10);
81
 
          
82
    String inputJson=JSONUtils.covertFromObjectToJson(bean);
83
    HttpRequest request = HttpRequest.newBuilder(URI.create(serviceURL+"updateProduct"))
84
            .header("Content-Type", "application/json")
85
            .PUT(HttpRequest.BodyPublishers.ofString(inputJson)).build();
86
    CompletableFuture<HttpResponse<String>> response = client.sendAsync(request,HttpResponse.BodyHandlers.ofString());
87
    if(response.get().statusCode() == 500)
88
        System.out.println("Product Not Avaialble to update");
89
    else {
90
        bean = JSONUtils.covertFromJsonToObject(response.get().body(), ProductBean.class);
91
        System.out.println(bean);
92
    }
93
    response.join();
94
}
95
//send request to delete the product by its productId
96
public static void deleteProduct() throws ExecutionException, InterruptedException, IOException
97
{
98
    HttpRequest request = HttpRequest.newBuilder(URI.create(serviceURL+"deleteProduct/1"))
99
            .DELETE().build();
100
    CompletableFuture<HttpResponse<String>> response = client.sendAsync(request,HttpResponse.BodyHandlers.ofString());
101
    if(response.get().statusCode() == 500)
102
        System.out.println("Product Not Available to delete");
103
    else {
104
        ProductBean bean = JSONUtils.covertFromJsonToObject(response.get().body(), ProductBean.class);
105
        System.out.println(bean);
106
    }
107
    response.join();
108
}
109
}
110
 
          



Run the application. You can observe Product details added in the database table.

Uncomment the getProductDetailsById() in the main method, comment the other methods and run the application you can observe the product details displayed in the console.

Likewise, you can comment and uncomment the functionalities provided in the main class and observe the results.

Conclusion

With the HttpClient client in Java 11, we can send different types of requests Synchronously/Asynchronously with support of HTTP/1.1 and HTTP 2. No need to add any external http client library to your project.

Topics:
http ,http request ,java ,java 11 ,rest web services ,spring boot ,tutorial

Opinions expressed by DZone contributors are their own.

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}