Creating RESTful APIs with Spring Boot 2 and MongoDB
In modern day software development, It is a prevalent practice for non-static apps or websites to access content resources over the internet which could be sourced from a third-party company or developed in-house for personal use. One of the most common ways to build such a content service is via the RESTful API, REST stands for Representational state transfer, API means Application Programming Interface, RESTful is just the adjective form of REST.
RESTful API is a software architectural style of exposing resources on a computer for accessing and manipulation through some set of stated operations with restrictions, basically it’s a way you can expose some data resources on your computer upon request through some endpoint defined by you.
In this write up, we will be building a RESTful API to access and manipulate students data over the network using Spring boot 2, a Java framework and MongoDB, a database system.
Let’s get started
What is Spring boot?
Last year, Netflix announced they would be migrating all of their back end services to Spring boot.
Spring boot is a layer built atop Spring, a popular, powerful and robust Java framework used to build Java Enterprise applications. Spring obliviates the quite stressful tasks which could be associated with building large Java applications by letting developers focus more on the business logic of the project they’re working on rather than the core technicalities of the language environment; but it requires some configuration XML files to properly enforce it’s core functionalities such as IoC(inversion of Control), dependency injection and so on. Meanwhile, spring boot removes the process of writing those mandatory configuration XML files, it uses annotations to wire our app components together to speed up development process.
Why are we using spring boot?
- It is lightweight and easy to understand and use.
- It shortens development time as it handles a lot of things for us behind the scene.
- It lets us build highly secure apps.
What is MongoDB?
MongoDB is an open source, NoSQL database system used for storing data, unlike a relational database, MongoDB stores data as documents in a rich JSON (JavaScript object notation) format which is enveloped as an object in a collection. For this app, we will have a students collection which stores a student document.
Why MongoDB?
- It has a cloud service we can utilize to store and retrieve our data rather than install and set-up locally on our PC.
- It’s very easy to use and work with for developers.
- we can store high volume of data.
How exactly will we achieve our aim with them?
What we will do is create a server application that lets our computer listen for incoming request from clients over the network and serves resources based upon the parameters of the request made. Spring boot handles our server creation with Apache Tomcat, so we can solely focus on the API logic. In this article, our computer will be connected to a MongoDB database, upon some http request method and perhaps payload, our student database is accessed for some data and modified, then a response is sent to the client (which could be a browser or script sending a request to our server).
What tools do we need for development?
- Java SDK which supports nothing less than Java 8 i.e Java v1.8, Spring boot 2.X would only support Java version above 7.
- An IDE (Integrated Development Environment) that supports Java, I will be using IntelliJ IDEA.
- POSTMAN, Google chrome API testing extension, rest client or any API test tool of your choice.
Let’s have our database in place
For storing students data, we will use the MongoDB cloud version, MongoDB Atlas to skip the process of setting up MongoDB on our computer. You can choose to skip this section if you have MongoDB already setup on your machine or have an existing MongoDB atlas account.
So let’s create an account and have our DB up and running at https://www.mongodb.com/cloud/atlas/register.
Fill in your details as shown above and click on the “Get started free” button.
The next page displays info about the cluster plans MongoDB Atlas offers, since we want to build a trivial app, choose the free shared cluster option and proceed.
Afterward, you will have to configure your cluster with respect to your location, but I will just move on with the default options.
After creating your cluster, you should see a cluster dashboard where you can setup connection to start using the database, click on the connect tab as shown below
Then an overlay displays with some connection configuration options, select the “Allow Access From Anywhere” option, then enter a username and password to create a MongoDB user for your database, then click on “Choose Connection Method”.
Moving on, select the option to use MongoDB from your application, then proceed to the “Connect” tab where you will be asked to select your driver and version, you can choose to leave the values as it is, we are more interested in the connection string, so copy and save it somewhere, we will make use of it to setup our spring boot database connection soon.
Once you’re done saving the connection string somewhere, we can move on with working with on the main app with Spring Boot.
Getting Our RESTful API In Shape
To get started with Spring Boot, We need to use the Spring initializr to bootstrap our app dependencies and others, so navigate to https://start.spring.io.
The page contains multiple config options to select from,then a zip file containing a starting template with respect to the options chosen will be generated when we’re done.
⦁ We will use maven as our project’s build tool and Spring Boot v2.3.3
⦁ fill the project metadata with whatever values you feel like using but maintain consistency just as I have done above.
⦁ Select JAR for packaging
⦁ I will use Java 8, so as to stick with the minimum Java functionalities Spring Boot requires.
⦁ For dependencies, search and select Spring WEB and Spring Data MongoDB
⦁ Click on Generate, you should have the studentsData zip file downloaded on your machine.
Proceed to opening the project folder with IntelliJ IDEA, your project should have its dependencies resolving which means our app’s required resources are being made available by maven, You can see the message at the mid bottom of IntelliJ. Open the studentsData\pom.xml and you should find all of the projects dependencies.
If intelliJ underlines some part of the xml file in red, it means the project’s dependencies weren’t resolved successfully, so right click on the “studentsData” folder under project at the left corner, find and click on maven, then click on “Generate Sources and Update Folders”, your project errors should be fixed some while after doing that.
Let’s setup our app to use MongoDB
If you have MongoDB installed on your machine and won’t be using MongoDB atlas, feel free to skip this part because Spring boot will automatically try to connect to MongoDB server at mongodb://localhost/test, just make sure you launch mongod on your terminal to start a MongoDB server on your machine.
Now, open src\main\resources\application.properties and set spring.data.mongodb.uri to the connection string you had saved earlier from MongoDB atlas, replace “<password>” in the connection string with your password, and set “<dbname>” to “studentsData”
Structuring Our Project
Spring Boot has several conventions for structuring projects, we will make use of the DAO pattern. We will structure our code into 4 packages inside the com.studentsData.students package and our entry java class, studentsDataApplication.java will remain directly within the com.studentsData.students package.
Understanding Our Project Structure
⦁ studentsDataApplication.java is our app’s entry class, it gets launched immediately we run our app.
⦁ The service package contains java class(es) related to the business logic of our application and calls the DAO to perform it’s function.
⦁ model defines the structure of data to be stored in our database.
⦁ DAO(Direct Access Object) defines and performs raw database operations
⦁ Repository contains an interface which helps with creation of custom database queries in addition to the already available ones.
⦁ api package contains REST Controller class that handles http requests made by clients and sends response.
Go ahead to create the Student.java class in the model package,
and type in the following lines of code
public class Student {
private final String name;
private final String department;
@Id
private String id;
public Student(@JsonProperty("name") String name, @JsonProperty("department") String department) {
this.name = name;
this.department = department;
}
public String getName() {
return name;
}
public String getDepartment() {
return department;
}
public String getId() {
return id;
}
}
The class defines the Student model, it contains the name, department and id fields to store the corresponding info about the student, notice the “@id” annotation before the id field, this informs spring boot to map the MongoDB auto-generated id to this field, @JSONProperty(“name”) and @JSONProperty(“department”) maps “name” and “department” keys of the JSON included as body of a post request to the name and department parameters of our Student constructor. We then defined getter methods to be used by Spring Boot to populate the Student object.
Now, move on to create the studentRepository interface inside the repository package, then type in the following code
public interface StudentRepository extends MongoRepository<Student, String> {
public Student findByName(String name);
}
This interface extends the MongoRepository class provided by Spring Data MongoDB, it let’s us create custom queries on our database in addition to the ones already provided by MongoDB such as findAll(), insert(), e.t.c. In this class, we declared a custom query method to find student by name, MongoDB will create the implementation of the class at runtime.
Moving forward, create StudentDAO.java interface inside the DAO package with the following code
public interface StudentDAO{
public List<Student> getAllStudents();
public Student getStudentById(String id);
public Student getStudentByName(String name);
public Student addStudent(Student student);
public Student updateStudent(Student student);
public void deleteStudent(Student student);
}
The DAO will be used to make transactions with MongoDB, so we created an interface that contained all methods that we will make use of to access and manipulate our database, you can add more if you want. Before we can make use of it, it’s implementation is crucial, still inside the DAO package, create StudentDAOImpl.java then type in the following code
@Repository
public class StudentDAOImpl implements StudentDAO{
@Autowired
private final StudentRepository studentRepository;
public StudentDAOImpl(StudentRepository studentRepository){
this.studentRepository = studentRepository;
}
@Override
public List<Student> getAllStudents() {
return studentRepository.findAll();
}
@Override
public Student addStudent(Student student) {
return studentRepository.insert(student);
}
@Override
public Student getStudentById(String id) {
Optional<Student> student = studentRepository.findById(id);
return student.get();
}
@Override
public Student getStudentByName(String name) {
return studentRepository.findByName(name);
}
@Override
public Student updateStudent(Student newStudent) {
return studentRepository.save(newStudent);
}
@Override
public void deleteStudent(Student student) {
studentRepository.delete(student);
}
}
The @Repository annotation informs Spring Boot that this class is a repository and the necessary attachments should be made. @Autowired helped us create object instance of StudentRepository (i.e the studentRepository data field) without making an explicit instance creation, this is handled by Spring Boot using dependency injection. So we’ve implemented all the methods declared in the StudentDAO interface by invoking methods of studentRepository.
Going further, we can now create the StudentService class which will mediate between StudentController and StudentDAO, create StudentService class inside the service package, then enter the following lines
@Service
public class StudentService {
private final StudentDAOImpl studentDAO;
@Autowired
public StudentService(StudentDAOImpl studentDAO) {
this.studentDAO = studentDAO;
}
public List<Student> getAllStudents(){
return studentDAO.getAllStudents();
}
public Student getStudent(String id){
return studentDAO.getStudentById(id);
}
public Student getStudentByName(String name){
return studentDAO.getStudentByName(name);
}
public Student addStudent(Student student){
return studentDAO.addStudent(student);
}
public Student updateStudent(Student student){
return studentDAO.updateStudent(student);
}
public void removeStudent(String id){
Student student = studentDAO.getStudentById(id);
studentDAO.deleteStudent(student);
}
}
This class uses the studentDAOImpl class methods to carry out operations on our database, dependency injection is also carried out here as indicated by @Autowired, we then created methods to create, get student(s) and update student data by calling the required studentDAOImpl methods. All that is left to do is to make use of this service in our REST controller class.
Create the StudentController.java class inside the api package, then input the following lines of code
@RequestMapping("api/v1/student")
@RestController
public class StudentController {
@Autowired
private final StudentService studentService;
public StudentController(StudentService studentService) {
this.studentService = studentService;
} @GetMapping
public List<Student> getAll(){
return studentService.getAllStudents();
}
@GetMapping(value = "{id}")
public Student getById(@PathVariable("id") String id){
return studentService.getStudent(id);
}
@PostMapping
public Student addStudent(@RequestBody Student student){
return studentService.addStudent(student);
}
@DeleteMapping(value = "{id}")
public void removeStudent(@PathVariable String id){
studentService.removeStudent(id);
}
}
@RestController and @RequestMapping(“api/v1/student”) annotate that this class is used to handle http requests, serves JSON, XML and custom response, and declares the request URI used to access our service which is “api/v1/student”, our app will only handle requests made to localhost:8080/api/v1/student.
As usual, the studentService field is auto-wired to create it’s instance implicitly, @GetMapping indicates the method will be used to handle a GET http request, getAll() returns all the students data in our database when a GET request is sent to localhost:8080/api/v1/student, @GetMapping(value=”{id}”) will handle request with dynamic URI that includes an id, the request URI will be localhost/api/v1/{id} where id is the id of the student we want to fetch from the database and the @PathVariable injects the id in the URI as argument for the method.
@PostMapping handles POST request, @RequestBody tells that the request requires a body whose values are used to create the student object which will be the argument for the addStudent method. @DeleteMapping handles the request to delete student specified by id in our database.
All of our project classes have been created and populated, let’s run our code by launching the app from studentsDataApplication.java.
If everything is properly set in your project files, you should have some messages logged in your console that looks like this
So Spring Boot has started a Tomcat server to listen for http requests, let’s proceed with testing our RESTful API.
Testing our REST API
I will use Postman for making http requests, you can use any API testing tool you feel comfortable using.
Launch Postman, open the build view, if you have another view opened, you can switch to build view by clicking on build at the bottom right of the app window.
Enter the REST API URI, localhost:8080/api/v1/student, using the GET method option, hit send
Notice the “200 ok” text on the right, this is an http status code which indicates that our http request was a success. The response is the empty square brackets which should contain students info saved in our database but is empty since we haven’t added any student to our database, let’s populate our database next.
Now, change the request method from “GET” to “POST”, and change the option in the Params dropdown directly below the “POST” dropdown from Params to Body, then create a JSON with the student’s name and department then hit send.
At the response section on the right side of the window, you can see we got a 200 status code and also, we got a JSON response containing our student’s info with an id attached, go on to add more students, then make a GET request to localhost:8080/api/v1/student to fetch all students info.
Now let’s fetch a student’s info with id, to do that, we will extend our request’s URI with the specific id and change the request method to GET, so let’s get Omooba Oreoluwa’s details using id.
Next, let’s delete a student’s info. I will add a new student with the name “Howard Robert” at Biochemistry, then I will use the delete http request with the generated id to delete the student from the database
The student data has been added to the database, now, let’s delete the student from the database,
Let’s check the list of students info in our collection, you can see Howard Robert isn’t present in our collection anymore.
At this point, we’ve verified the functionality of the RESTful API we’ve created and can make request based on the operations we’ve defined. You can go further to add more operations to manipulate our database inside the REST Controller class.
You can find the project’s code at https://github.com/Ahmodadeola/studentsDataApi_with_SpringBoot2.git.
Congrats, you can now build RESTful APIs with Spring Boot, go explore more about Spring Boot and build greater apps.