O que é HATEOAS ?
HATEOAS ou (Hypertext as the Engine of Application State) é um modelo que permite que você navegue entre seus endpoints de forma dinâmica através de links e URLs e sem precisar do conhecimento prévio sobre a API. Nesse caso o cliente descobrirá as URLs conforme navega entre seus recursos.
Uma boa forma de comparação de HATEOAS é o Hypertext ou Hipertexto que é comum para quem navega na internet diariamente. Quando estamos pesquisando por algo na internet ou lendo alguma notícia e nos deparamos com alguma informação que nos direciona para outro link.
O mesmo conceito pode ser aplicado a API em que a aplicação consumidora terá um link inicial e a partir dele terá acesso a outros recursos caso necessário.
Spring-HATEOAS é uma biblioteca de APIs que podemos usar para criar representações REST que seguem o padrão HATEOAS.
Vamos construir uma aplicação simples com o objetivo de mostrar as vantagens de usar o HATEOAS
- Primeiro adicionamos a dependência do spring-HATEOAS
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-hateoas</artifactId>
</dependency>
- Criaremos um model
@Entity
public class Employee {
private @Id @GeneratedValue Long id;
private String name;
private String role;
public Employee() {}
public Employee(String name, String role) {
this.name = name;
this.role = role;
}
//gets and sets
- Depois vamos implementar a seguinte lógica no nosso controller
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.linkTo;
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.methodOn;
import java.util.List;
import java.util.Optional;
import java.util.stream.Collectors;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.CollectionModel;
import org.springframework.hateoas.EntityModel;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import com.example.demo.exception.EmployeeNotFoundException;
import com.example.demo.model.Employee;
import com.example.demo.repository.EmployeeRepository;
@RestController
public class EmployeeController {
@Autowired
private EmployeeRepository repository;
@GetMapping("/employees")
public ResponseEntity<CollectionModel<EntityModel<Employee>>> all() {
List<EntityModel<Employee>> employees = repository.findAll().stream()
.map(employee -> EntityModel.of(employee,
linkTo(methodOn(EmployeeController.class).one(employee.getId())).withSelfRel()))
.collect(Collectors.toList());
return ResponseEntity.ok(CollectionModel.of(employees));
}
@GetMapping("/employees/{id}")
public ResponseEntity<EntityModel<Employee>> one(@PathVariable Long id) {
Employee employee = repository.findById(id)
.orElseThrow(() -> new EmployeeNotFoundException(id));
return ResponseEntity.of(Optional.of(EntityModel.of(employee,
linkTo(methodOn(EmployeeController.class).all()).withRel("employees"))));
}
}
O methodOn() obtém o mapeamento do método fazendo uma invocação fictícia do método de destino.
O método linkTo() inspeciona a classe do controlador e obtém seu mapeamento raiz e finalmente, o withSelfRel() qualifica a relação como um link próprio.
Nesse exemplo usamos o CollectionModel ele auxilia na criação de um wrapper para uma coleção de entidades.
No final temos o seguinte resultado
Se listarmos todos os employees, ele vai retornar no json um link para acessar cada employee individualmente, caso seja necessário.
Se fizemos uma busca por apenas um employee ele nos retorna no json um link para acessar todos os employees
Esse é um exemplo simples onde vemos que o cliente pode ter um único ponto de entrada para a aplicação e outras ações podem ser tomadas com base na resposta.
Nessa aplicação eu mostrei como Spring HATEOAS promove a descoberta de API em um serviço rest.
link do repositório com o código fonte projeto-exemplo
Top comments (2)
Parabéns pelo artigo.
Tem um typo no título =]
Excelente artigo!