Spring Boot HATEOAS

In this tutorial, we will be discussing about the Spring boot HATEOAS (learn about HATEOAS from here) which stands for Hypermedia as the engine of application state. Whenever we visit a web application, we also find some hyperlinks that allow us to do multiple activities. For example, on the home page of any internet banking website, we can find multiple options such as view transactions, view balance, make a transaction, add a payee, etc. All these hyperlinks provide multiple information. Let us implement a HATEOAS technique in this tutorial.

Creating Spring Boot HATEOAS Compliant REST API

We are developing an API that will allow us to save details related to a student.

In the earlier examples, we have created POJOs named Teacher.java, Student.java in the package com.tutorial.studytonight.pojo.

We will save the details of the student in a java.util.Map and will fetch the details of the Student from another GET end point.

When a user requests for any Student data, we will provide the requested data along with the link to overall Students available as a part of additional information.

Add the below code to ResourceController.java which we created earlier. The previous code is removed purposefully to emphasize on this example.

@RestController
public class ResourceController {

    @PostMapping("/saveStudent")
    public void saveStudent(@RequestBody Student student){
        resourceService.saveStudent(student);
    }

    @GetMapping("/getAllStudents")
    public Map<Integer,Student> allStudents(){
        return resourceService.allStudents();
    }

    @GetMapping("/getStudentDetails/{id}")
    public Resource<Student> getStudentDetails(@PathVariable("id") int id){
        Student student=resourceService.getStudentDetails(id);
        ControllerLinkBuilder link=linkTo(methodOn(this.getClass()).allStudents());
        Resource<Student> resource=new Resource<Student>(student);
        resource.add(link.withRel("all-students"));
        return resource;
    }
}

The end points defined in the Resource controller class above are used to save students data and retrieve the details of the students from the Map.

Spring HATEOS provides classes such as ControllerLinkBuilder that help us in enabling HATEOAS principles while developing REST services using spring boot.

We need to import the static methods of the class ControllerLinkBuilder using the import static statement. Let's have a simple example to explain how and when we use the import static statement.

package com.airline;

Class Airline{
            
    public static String airLicense;
    public static String headQuarters;
            
    public static String getLicense() {
        return airLicense;
    }

    public void getData(){
        //  Statements
    }

}

To import the static members of the above Airline class, we need to use import static statement as follows: import static com.airline.Airline.*;

In the above specified endpoints, we have methods from ControllerLinkBuilder such as methodOn, linkTo, etc which are static.

methodOn(Class<T>) returns the class<T> reference which is passed as the argument and it is in-turn passed to linkTo(Class<T>) method which returns the reference of ControllerLinkBuilder.

Resource is another class which is used to add the link returned by the ControllerLinkBuilder and to provide the custom name to the link we use the method withRel(String name) from ControllerLinkBuilder class.

Resource is the instance which contain the individual Student details requested for along with HATEOAS link related to all the students.

We need to make changes in the service layer and repository layer as well. Add the below code to ResourceService.java which we created earlier.

public class ResourceService {

    public void saveStudent(Student student){
        repository.saveStudent(student);
    }

    public Map<Integer,Student> allStudents(){
        return repository.allStudents();
    }

    public Student getStudentDetails(int id){
        return repository.getStudentDetails(id);
    }
}

Add the below code to the ResourceRepository.java which we created earlier.

@Repository
public class ResourceRepository {              

    public void saveStudent(Student student){
        studentMap.put(student.getId(),student);
    }

    public Map<Integer,Student> allStudents(){
        return studentMap;
    }

    public Student getStudentDetails(int id){
        return studentMap.get(id);
    }
}

Testing the API

Let us save the details of student as seen in the below screenshot.

testing HATEOAS compliant REST service in spring boot

The POST request was successful and 200 OK status can be seen in the bottom right-corner.

We can create one more POST request to store the details so that we can view multiple students data.

Now let us get an individual Student information which also returns the HATEOAS link for all the available students.

testing HATEOAS compliant REST service in spring boot

Conclusion: In this tutorial, we have seen the importance of spring HATEOAS and implemented it using an example. An important thing to note here is that spring boot provides loose coupling between HATEOAS and URIs mapped with the end points. It is because we are not concerned if the URI pattern changes as we are capturing the HATEOAS link from the end point to which it was mapped.