External API with Java, Spring Boot and Gradle
A step-by-step simple guide showing how to consume an external API using Java, Spring Boot and Gradle
In this tutorial, we are using the Studio Ghibli API.
Note: originally, this article was written using the API address https://ghibliapi.herokuapp.com/, which is currently off air. It seems that the same API was transferred to https://ghibliapi.vercel.app/.
Setting up the environment
As usual, we are going to use Spring Initializr, which is a tool to speed up the process of building and configuring the base structure of our application.
As you can see, we are only using Spring Web and Spring Boot Dev Tools dependencies. The first helps us to build web and RESTful applications, while the latter provides us with fast restarts to our application. Since we are not dealing with databases at the moment, we are not going to select Spring Data JPA or a database driver dependencies for now. If we intend to connect to a database later, we can just add new dependencies to our project at any time.
After downloading the ZIP provided by Spring Initializr, we can import the project to our IDE. Here I’m using IntelliJ IDEA.
Unlike Maven, where the dependencies are built through the pom.xml file, in Gradle we have the build.gradle file to set our configuration and dependencies.
Once that’s done, we can start to write the code of our application.
And since we are keeping it as simpler as it can be, we are going to consume an API that requires no authentication. There are a lot of fun free APIs to choose from. As said before, here we are going to use the Studio Ghibli API.
Project architecture, classes, and endpoints
In this project, we are going to use the Controller-Service-Model architecture. It comes in handy when we are working with small REST applications.
So, let’s start with our model.
Model
Since we are dealing with Studio Ghibli, the main objects of our application are going to be the films. Thus, in the package model, we can create the Film class. For now, we are going to have only three attributes: title, original_title and original_title_romanised. We must write exactly like that, because that is the way those fields are written in the API (to verify it, you can go to the documentation).
In the realm of OOP (Object-Oriented Programming), like always, we must have the getter methods. As we are not using Lombok, we must write them on our own.
Then our Film class will look like this:
Now we move to the Service layer.
Service
Like always, we first create our service package. Then we create the FilmService class in it. The first thing we must do after creating our class is to write the @Service Spring annotation.
Then, we must instantiate a RestTemplate object and mark it with the @Autowired annotation (as we are dealing with dependency injection).
At this moment, we are going to have only two methods. The first one will consume the Ghibli API and return all its information. We will call this method findAllFilmsComplete. This method will return an Object array. We get this array through the template we declared before, using its getForObject method and passing the API URL as a parameter.
Our second method will be findAllFilms, which will return an array of Film objects. Likewise, we use the getForObject method and pass the API URL as a parameter. The difference here is that we are using the Film class (i.e., our model). This means that the fields that will be returned will only be the ones we wrote as attributes in the Film class — so we won’t have the complete information about the films, but only the ones we chose.
Our FilmService class will look like this:
Controller
Last, but not least, we must write our FilmController class in the controller package. First, we mark the class with the @RestController and @RequestMapping Spring annotations. Then we declare a FilmService object with the @Autowired annotation.
Now we just have to write the methods that will call the service methods. To call the findAllFilmsComplete method, we create a getAllFilmsComplete method that also returns an Object array and annotate it with @GetMapping (passing the path we will call as a parameter).
And to call the findAllFilms method, we create a getAllFilms method that returns an array of Film objects. We also annotate it with @GetMapping, but this time we don’t need to pass a parameter, since we want to call it at the root URL.
Here is how our controller class will look like:
You may have noticed that we are not working with a Repository layer in our architecture. The reason is that, for now, we are not connecting to a database, therefore we are not saving any information. That’s why we don’t need repositories and DTOs.
There is only one step left for us to run and test our application. In the ExternalApiApplication class (the one that was created automatically by Spring Initializr), we must create a method that builds (through a RestTemplateBuilder) and returns a RestTemplate and mark it with @Bean Spring annotation. As the documentation points out, this annotation is used to indicate that a method produces a bean to be managed by the Spring container.
It will look like this:
Now we are good to go and test our API consumption with Postman.
Testing with Postman
After running the Spring Boot Application, we can go to Postman and make a GET request to our http://localhost:8080/.
As you can see, it returned all of Ghibli’s movies with the fields we defined in our Film class.
If we make a request to http://localhost:8080/complete, it will return all the movies with their complete information, just like when we make a request directly to the original API URL.
With that, we have presented the basics of how to consume an external API using Java, Spring Boot and Gradle.
But now we can move forward and have some fun.
Creating methods to improve our searches
Find by title
One way to improve our queries to the API is, for example, to create a method that will find all the movies containing the word (or part of the word) that you typed.
For instance, we can write the method findFilmsByTitle in our service class, like shown above, and call it in the controller, like shown below.
When we make the request to the path http://localhost:8080/title passing the parameter “ki”, for example, we get all the movies that contain this substring. Notice that it works with the “title” as much as with the “original_title_romanised” fields, and also with lower and upper cases.
Adding more attributes to Film class
In order to get more information about the movies, we can add to our Film class more attributes that correspond to the JSON fields.
Only by adding the attributes and their getters to our class, we will have them returned when we make a request to our root path.
Listing the directors
We can also get a list with the names of all directors that worked on Studio Ghibli’s movies. One way of doing that is by creating a method like this in the service class:
Getting the newest movies
Another interesting listing we can make is sort the movies from the newest to the oldest. For that, we can create two methods: a private one just to sort a list, and a public one that will get the list and call the first one to sort it and return it. It could be something like this:
Improving the code and testing (again) on Postman
You may have noticed that we are not using our template on each method anymore. Since a lot of our methods are using the same object, it was better to declare it only once, at the beginning of our class:
Then we can call our new service methods in our controller class, like this:
In Postman, when we make requests to the “directors” endpoint, we get a list of all directors that were part of a Ghibli film:
And if we request the “newest” endpoint, we will get a list with all the movies, from the newest to the oldest:
Conclusion
That is how you can consume an external API and have fun with it in your application. There are many methods that you can create, to get many different information about Studio Ghibli’s movies. Be creative and keep exploring this and other APIs.
You can access the entire code of this project in GitHub.
Are you familiar with the best practices to build a consistent and robust REST API? Check the article API REST: confira as 9 melhores práticas (it is in Portuguese, but feel free to use a translator).