Minimal Graphql client request with Springboot #
https://unsplash.com/license Photo from Farzad Nazifi under Unsplash Licence
Introduction #
Most API’s architectural styles are RESTful. For some good reasons, APIs can also be built based on a Graphql architecture style. I recently had the opportunity to call one of them. I discovered and tried several ways to perform this Graphql request, all with pros and cons. In this article, I will describe how to perform a minimal Graphql client request with Spring Boot and WebClient.
Requirements #
A Spring Boot Project is mandatory. I am using maven here.
Dependencies #
Mandatory #
WebFlux dependency to get WebClient:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-webflux</artifactId>
</dependency>
Starter Test dependency:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
to make sure Spring Application Context loads:
Optional #
Lombok because it saves boilerplate code:
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
Graphql Server #
I found this public Countries Graphql API from trevorblades. This API uses this Countries List as data sources.
Graphql Client #
Graphql request body #
1 Basic curl to get familiar with Graphql client request #
A Graphql request requires a body request containing at least a query. Optionally a variable and an operationName. (operationName is only required if multiple operations are present in the query. I don’t use it in this tutorial).
Just like this curl example:
curl \
--location \
--request POST 'https://countries.trevorblades.com/' \
--header 'Content-Type: application/json' \
--data-raw '{"query":"query { \n country(code: \"BE\") { \n name\n capital\n currency\n }\n}","variables":{}}'
You may copy/paste it into your terminal. The response should look like this
{
"data": {
"country": {
"name": "Belgium",
"capital": "Brussels",
"currency": "EUR"
}
}
}
So far we have a working Graphql curl request. Let’s now code it in java.
2. Java Graphql query #
2.1 GraphqlRequestBody #
Let’s create the GraphqlRequestBody object.
2.2 Graphql Query #
Let’s now create a getCountryDetails.graphql
file in the resources folder of the project.
query($code: ID!) {
country(code: $code) {
name
capital
currency
}
}
2.3 Graphql Variables #
Let’s create a variables.graphql
file in the resources folder.
{
"code" : "countryCode"
}
Graphql response #
Now that I have my Graphql request body and based on what I’m expecting from the API, let’s handle the response
Data Transfer Object #
I create my CountryDto
Object :
@Getter
public class CountryDto {
private CountryData data;
@Getter
public class CountryData {
private Country country;
@Getter
public class Country {
private String name;
private String capital;
private String currency;
}
}
}
Eventually, let’s create the CountryClient
class 😀.
I said it was a minimal Graphql client request, didn’t I?
@Service
@Slf4j
public class CountryClient {
private final String url;
public CountryClient(@Value("https://countries.trevorblades.com/") String url) {
this.url = url;
}
public CountryDto getCountryDetails(final String countryCode) throws IOException {
WebClient webClient = WebClient.builder().build();
GraphqlRequestBody graphQLRequestBody = new GraphqlRequestBody();
final String query = GraphqlSchemaReaderUtil.getSchemaFromFileName("getCountryDetails");
final String variables = GraphqlSchemaReaderUtil.getSchemaFromFileName("variables");
graphQLRequestBody.setQuery(query);
graphQLRequestBody.setVariables(variables.replace("countryCode", countryCode));
return webClient.post()
.uri(url)
.bodyValue(graphQLRequestBody)
.retrieve()
.bodyToMono(CountryDto.class)
.block();
}
}
GraphqlSchemaReaderUtil
class to read Graphql files stored in the resource folder:
@Slf4j
public final class GraphqlSchemaReaderUtil {
public static String getSchemaFromFileName(final String filename) throws IOException {
return new String(
GraphqlSchemaReaderUtil.class.getClassLoader().getResourceAsStream("graphql/" + filename + ".graphql").readAllBytes());
}
}
Let’s just log the Graphql response in the main method of our Spring Boot App:
@SpringBootApplication
@Slf4j
public class GraphqlClientApplication {
public static void main(String[] args) throws IOException {
ConfigurableApplicationContext context = SpringApplication.run(GraphqlClientApplication.class, args);
CountryClient client = (CountryClient) context.getBean("countryClient");
ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
CountryDto countryDto = client.getCountryDetails("BE");
log.info(ow.writeValueAsString(countryDto));
}
}
Now, your console should log the response like this:
Unit Test #
Unit test with MockWebServer can be found here.
TL;DR #
Go to Github Repo.