Overview
I will introduce how to call third-party API in Spring Boot project. We'll send GET request to this resource https://sampleapis.com/api-list/coffee, then display response data in view (browser).
Prerequisites
You need these knowledge at basic level:
- Java
- Spring Boot
- Thymeleaf
Development process
Create Project
Go to https://start.spring.io/ and generate a project with these dependencies:
Unzip the file and open the project in your code editor. I use Intellij community edition.
Create Controller
import com.myproject.apidemo.Coffee;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.reactive.function.client.WebClient;
@Controller
public class CoffeeController {
@GetMapping("/coffee")
public String coffee(Model model) {
String url = "https://api.sampleapis.com/coffee/hot";
WebClient.Builder builder = WebClient.builder();
String coffeeList = builder.build()
.get()
.uri(url)
.retrieve()
.bodyToMono(String.class)
.block();
System.out.println("---------------------");
System.out.println(coffeeList);
model.addAttribute("coffeeList", coffeeList);
return "coffee";
}
}
If you can't import some of them, then one possible problem is Maven doesn't load your pom.xml file correctly. Reloading the project resolves this issue in my case.
You can directly type url in your browser and check the response data, it is a list of coffee in JSON format.
You can map response data to Java object if you want. For this, you need to create Coffee class and define fields that you want to hold as Coffee object. For me, Coffee class has two fields, title and description. This way, when response data maps to Coffee object, the object only holds title and description from response JSON data.
package com.myproject.todoapp;
public class Coffee {
String title;
String description;
public Coffee() {
}
public Coffee(String title, String description) {
this.title = title;
this.description = description;
}
// getters and setters
// toString method
}
import com.myproject.apidemo.Coffee;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.reactive.function.client.WebClient;
@Controller
public class CoffeeController {
@GetMapping("/coffee")
public String coffee(Model model) {
String url = "https://api.sampleapis.com/coffee/hot";
WebClient.Builder builder = WebClient.builder();
List<Coffee> coffeeList = builder.build()
.get()
.uri(url)
.retrieve()
.bodyToMono(new ParameterizedTypeReference<List<Coffee>>() {
})
.block();
System.out.println("---------------------");
System.out.println(coffeeList);
model.addAttribute("coffeeList", coffeeList);
return "coffee";
}
}
In this tutorial, I prefer converting the response data to Coffee object, so I stick to second version implementation.
Create View page
Finally we need view page just to display list of coffee:
<!doctype html>
<html lang="en" xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Coffee</title>
</head>
<body>
<h3>Coffee List</h3>
<table>
<tbody>
<tr th:each="coffee: ${coffeeList}">
<td th:text="${coffee.title}"></td>
<td th:text="${coffee.description}"></td>
</tr>
</tbody>
</table>
</body>
</html>
Done! Now you should be able to get data from http://localhost:8080/coffee.
Refactoring code
Although we could successfully call the API, there's a room for improvement. Currently coffee method instantiates WebClient.Builder object each time when it gets called. This is unnecessary overhead. Better implementation is creating separate file that configures WebClient.Builder.
Create configuration file for WebClient:
@Configuration
public class WebClientConfig {
@Bean
public WebClient webClient(WebClient.Builder builder) {
return builder.build();
}
}
Inject the Bean to our Controller class:
private WebClient webClient;
@Autowired
public ToDoListController(WebClient webClient) {
this.webClient = webClient;
}
@GetMapping("/coffee")
public String coffee(Model model) {
String url = "https://api.sampleapis.com/coffee/hot";
List<Coffee> coffeeList = webClient
.get()
.uri(url)
.retrieve()
.bodyToMono(new ParameterizedTypeReference<List<Coffee>>() {
})
.block();
// other code
}
Now Spring Boot automatically instantiates and manages WebClient object behind the scene.
Top comments (0)