Polishing.
This commit is contained in:
@@ -30,6 +30,7 @@ class DatabaseLoader {
|
||||
@Bean
|
||||
CommandLineRunner initDatabase(EmployeeRepository employeeRepository, ManagerRepository managerRepository) {
|
||||
return args -> {
|
||||
|
||||
/*
|
||||
* Gather Gandalf's team
|
||||
*/
|
||||
|
||||
@@ -35,17 +35,14 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
@NoArgsConstructor
|
||||
class Employee {
|
||||
|
||||
@Id @GeneratedValue
|
||||
private Long id;
|
||||
@Id @GeneratedValue private Long id;
|
||||
private String name;
|
||||
private String role;
|
||||
|
||||
/**
|
||||
* To break the recursive, bi-directional relationship, don't serialize {@literal manager}.
|
||||
*/
|
||||
@JsonIgnore
|
||||
@OneToOne
|
||||
private Manager manager;
|
||||
@JsonIgnore @OneToOne private Manager manager;
|
||||
|
||||
Employee(String name, String role, Manager manager) {
|
||||
|
||||
|
||||
@@ -18,8 +18,8 @@ package org.springframework.hateoas.examples;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
import org.springframework.hateoas.EntityModel;
|
||||
import org.springframework.hateoas.CollectionModel;
|
||||
import org.springframework.hateoas.EntityModel;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
@@ -36,7 +36,7 @@ class EmployeeController {
|
||||
private final EmployeeWithManagerResourceAssembler employeeWithManagerResourceAssembler;
|
||||
|
||||
EmployeeController(EmployeeRepository repository, EmployeeRepresentationModelAssembler assembler,
|
||||
EmployeeWithManagerResourceAssembler employeeWithManagerResourceAssembler) {
|
||||
EmployeeWithManagerResourceAssembler employeeWithManagerResourceAssembler) {
|
||||
|
||||
this.repository = repository;
|
||||
this.assembler = assembler;
|
||||
@@ -45,30 +45,30 @@ class EmployeeController {
|
||||
|
||||
/**
|
||||
* Look up all employees, and transform them into a REST collection resource using
|
||||
* {@link EmployeeRepresentationModelAssembler#toCollectionModel(Iterable)}. Then return them through
|
||||
* Spring Web's {@link ResponseEntity} fluent API.
|
||||
* {@link EmployeeRepresentationModelAssembler#toCollectionModel(Iterable)}. Then return them through Spring Web's
|
||||
* {@link ResponseEntity} fluent API.
|
||||
*/
|
||||
@GetMapping("/employees")
|
||||
public ResponseEntity<CollectionModel<EntityModel<Employee>>> findAll() {
|
||||
return ResponseEntity.ok(
|
||||
assembler.toCollectionModel(repository.findAll()));
|
||||
|
||||
return ResponseEntity.ok(assembler.toCollectionModel(repository.findAll()));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up a single {@link Employee} and transform it into a REST resource using
|
||||
* {@link EmployeeRepresentationModelAssembler#toModel(Object)}. Then return it through
|
||||
* Spring Web's {@link ResponseEntity} fluent API.
|
||||
* {@link EmployeeRepresentationModelAssembler#toModel(Object)}. Then return it through Spring Web's
|
||||
* {@link ResponseEntity} fluent API.
|
||||
*
|
||||
* @param id
|
||||
*/
|
||||
@GetMapping("/employees/{id}")
|
||||
public ResponseEntity<EntityModel<Employee>> findOne(@PathVariable long id) {
|
||||
|
||||
return repository.findById(id)
|
||||
.map(assembler::toModel)
|
||||
.map(ResponseEntity::ok)
|
||||
.orElse(ResponseEntity.notFound().build());
|
||||
return repository.findById(id) //
|
||||
.map(assembler::toModel) //
|
||||
.map(ResponseEntity::ok) //
|
||||
.orElse(ResponseEntity.notFound().build());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,27 +79,27 @@ class EmployeeController {
|
||||
*/
|
||||
@GetMapping("/managers/{id}/employees")
|
||||
public ResponseEntity<CollectionModel<EntityModel<Employee>>> findEmployees(@PathVariable long id) {
|
||||
return ResponseEntity.ok(
|
||||
assembler.toCollectionModel(repository.findByManagerId(id)));
|
||||
|
||||
return ResponseEntity.ok(assembler.toCollectionModel(repository.findByManagerId(id)));
|
||||
}
|
||||
|
||||
@GetMapping("/employees/detailed")
|
||||
public ResponseEntity<CollectionModel<EntityModel<EmployeeWithManager>>> findAllDetailedEmployees() {
|
||||
|
||||
return ResponseEntity.ok(
|
||||
employeeWithManagerResourceAssembler.toCollectionModel(
|
||||
StreamSupport.stream(repository.findAll().spliterator(), false)
|
||||
.map(EmployeeWithManager::new)
|
||||
.collect(Collectors.toList())));
|
||||
return ResponseEntity.ok( //
|
||||
employeeWithManagerResourceAssembler.toCollectionModel( //
|
||||
StreamSupport.stream(repository.findAll().spliterator(), false) //
|
||||
.map(EmployeeWithManager::new) //
|
||||
.collect(Collectors.toList())));
|
||||
}
|
||||
|
||||
@GetMapping("/employees/{id}/detailed")
|
||||
public ResponseEntity<EntityModel<EmployeeWithManager>> findDetailedEmployee(@PathVariable Long id) {
|
||||
|
||||
return repository.findById(id)
|
||||
.map(EmployeeWithManager::new)
|
||||
.map(employeeWithManagerResourceAssembler::toModel)
|
||||
.map(ResponseEntity::ok)
|
||||
.orElse(ResponseEntity.notFound().build());
|
||||
return repository.findById(id) //
|
||||
.map(EmployeeWithManager::new) //
|
||||
.map(employeeWithManagerResourceAssembler::toModel) //
|
||||
.map(ResponseEntity::ok) //
|
||||
.orElse(ResponseEntity.notFound().build());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@ package org.springframework.hateoas.examples;
|
||||
|
||||
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*;
|
||||
|
||||
import org.springframework.hateoas.EntityModel;
|
||||
import org.springframework.hateoas.CollectionModel;
|
||||
import org.springframework.hateoas.EntityModel;
|
||||
import org.springframework.hateoas.SimpleIdentifiableRepresentationModelAssembler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -41,21 +41,21 @@ class EmployeeRepresentationModelAssembler extends SimpleIdentifiableRepresentat
|
||||
public void addLinks(EntityModel<Employee> resource) {
|
||||
|
||||
/**
|
||||
* Add some custom links to the default ones provided.
|
||||
*
|
||||
* NOTE: To replace default links, don't invoke {@literal super.addLinks()}.
|
||||
* Add some custom links to the default ones provided. NOTE: To replace default links, don't invoke
|
||||
* {@literal super.addLinks()}.
|
||||
*/
|
||||
super.addLinks(resource);
|
||||
|
||||
resource.getContent().getId()
|
||||
.ifPresent(id -> {
|
||||
// Add additional links
|
||||
resource.add(linkTo(methodOn(ManagerController.class).findManager(id)).withRel("manager"));
|
||||
resource.add(linkTo(methodOn(EmployeeController.class).findDetailedEmployee(id)).withRel("detailed"));
|
||||
resource.getContent().getId() //
|
||||
.ifPresent(id -> { //
|
||||
// Add additional links
|
||||
resource.add(linkTo(methodOn(ManagerController.class).findManager(id)).withRel("manager"));
|
||||
resource.add(linkTo(methodOn(EmployeeController.class).findDetailedEmployee(id)).withRel("detailed"));
|
||||
|
||||
// Maintain a legacy link to support older clients not yet adjusted to the switch from "supervisor" to "manager".
|
||||
resource.add(linkTo(methodOn(SupervisorController.class).findOne(id)).withRel("supervisor"));
|
||||
});
|
||||
// Maintain a legacy link to support older clients not yet adjusted to the switch from "supervisor" to
|
||||
// "manager".
|
||||
resource.add(linkTo(methodOn(SupervisorController.class).findOne(id)).withRel("supervisor"));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -65,7 +65,7 @@ class EmployeeRepresentationModelAssembler extends SimpleIdentifiableRepresentat
|
||||
*/
|
||||
@Override
|
||||
public void addLinks(CollectionModel<EntityModel<Employee>> resources) {
|
||||
|
||||
|
||||
super.addLinks(resources);
|
||||
|
||||
resources.add(linkTo(methodOn(EmployeeController.class).findAllDetailedEmployees()).withRel("detailedEmployees"));
|
||||
|
||||
@@ -26,16 +26,15 @@ import com.fasterxml.jackson.annotation.JsonPropertyOrder;
|
||||
* @author Greg Turnquist
|
||||
*/
|
||||
@Value
|
||||
@JsonPropertyOrder({"id", "name", "role", "manager"})
|
||||
@JsonPropertyOrder({ "id", "name", "role", "manager" })
|
||||
public class EmployeeWithManager {
|
||||
|
||||
@JsonIgnore
|
||||
private final Employee employee;
|
||||
|
||||
@JsonIgnore private final Employee employee;
|
||||
|
||||
public Long getId() {
|
||||
|
||||
return this.employee.getId()
|
||||
.orElseThrow(() -> new RuntimeException("Couldn't find anything."));
|
||||
|
||||
return this.employee.getId() //
|
||||
.orElseThrow(() -> new RuntimeException("Couldn't find anything."));
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
||||
@@ -36,7 +36,8 @@ class EmployeeWithManagerResourceAssembler implements SimpleRepresentationModelA
|
||||
@Override
|
||||
public void addLinks(EntityModel<EmployeeWithManager> resource) {
|
||||
|
||||
resource.add(linkTo(methodOn(EmployeeController.class).findDetailedEmployee(resource.getContent().getId())).withSelfRel());
|
||||
resource.add(
|
||||
linkTo(methodOn(EmployeeController.class).findDetailedEmployee(resource.getContent().getId())).withSelfRel());
|
||||
resource.add(linkTo(methodOn(EmployeeController.class).findOne(resource.getContent().getId())).withRel("summary"));
|
||||
resource.add(linkTo(methodOn(EmployeeController.class).findAllDetailedEmployees()).withRel("detailedEmployees"));
|
||||
}
|
||||
|
||||
@@ -37,15 +37,14 @@ import com.fasterxml.jackson.annotation.JsonIgnore;
|
||||
@NoArgsConstructor
|
||||
class Manager {
|
||||
|
||||
@Id @GeneratedValue
|
||||
private Long id;
|
||||
@Id @GeneratedValue private Long id;
|
||||
private String name;
|
||||
|
||||
/**
|
||||
* To break the recursive, bi-directional interface, don't serialize {@literal employees}.
|
||||
*/
|
||||
@JsonIgnore
|
||||
@OneToMany(mappedBy = "manager")
|
||||
@JsonIgnore //
|
||||
@OneToMany(mappedBy = "manager") //
|
||||
private List<Employee> employees = new ArrayList<>();
|
||||
|
||||
Manager(String name) {
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
*/
|
||||
package org.springframework.hateoas.examples;
|
||||
|
||||
import org.springframework.hateoas.EntityModel;
|
||||
import org.springframework.hateoas.CollectionModel;
|
||||
import org.springframework.hateoas.EntityModel;
|
||||
import org.springframework.http.ResponseEntity;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.PathVariable;
|
||||
@@ -39,30 +39,31 @@ class ManagerController {
|
||||
|
||||
/**
|
||||
* Look up all managers, and transform them into a REST collection resource using
|
||||
* {@link ManagerRepresentationModelAssembler#toCollectionModel(Iterable)}. Then return them through
|
||||
* Spring Web's {@link ResponseEntity} fluent API.
|
||||
* {@link ManagerRepresentationModelAssembler#toCollectionModel(Iterable)}. Then return them through Spring Web's
|
||||
* {@link ResponseEntity} fluent API.
|
||||
*/
|
||||
@GetMapping("/managers")
|
||||
ResponseEntity<CollectionModel<EntityModel<Manager>>> findAll() {
|
||||
return ResponseEntity.ok(
|
||||
assembler.toCollectionModel(repository.findAll()));
|
||||
|
||||
return ResponseEntity.ok( //
|
||||
assembler.toCollectionModel(repository.findAll()));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Look up a single {@link Manager} and transform it into a REST resource using
|
||||
* {@link ManagerRepresentationModelAssembler#toModel(Object)}. Then return it through
|
||||
* Spring Web's {@link ResponseEntity} fluent API.
|
||||
* {@link ManagerRepresentationModelAssembler#toModel(Object)}. Then return it through Spring Web's
|
||||
* {@link ResponseEntity} fluent API.
|
||||
*
|
||||
* @param id
|
||||
*/
|
||||
@GetMapping("/managers/{id}")
|
||||
ResponseEntity<EntityModel<Manager>> findOne(@PathVariable long id) {
|
||||
|
||||
return repository.findById(id)
|
||||
.map(assembler::toModel)
|
||||
.map(ResponseEntity::ok)
|
||||
.orElse(ResponseEntity.notFound().build());
|
||||
return repository.findById(id) //
|
||||
.map(assembler::toModel) //
|
||||
.map(ResponseEntity::ok) //
|
||||
.orElse(ResponseEntity.notFound().build());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -73,7 +74,8 @@ class ManagerController {
|
||||
*/
|
||||
@GetMapping("/employees/{id}/manager")
|
||||
ResponseEntity<EntityModel<Manager>> findManager(@PathVariable long id) {
|
||||
return ResponseEntity.ok(
|
||||
assembler.toModel(repository.findByEmployeesId(id)));
|
||||
|
||||
return ResponseEntity.ok( //
|
||||
assembler.toModel(repository.findByEmployeesId(id)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@ package org.springframework.hateoas.examples;
|
||||
|
||||
import static org.springframework.hateoas.server.mvc.WebMvcLinkBuilder.*;
|
||||
|
||||
import org.springframework.hateoas.EntityModel;
|
||||
import org.springframework.hateoas.CollectionModel;
|
||||
import org.springframework.hateoas.EntityModel;
|
||||
import org.springframework.hateoas.SimpleIdentifiableRepresentationModelAssembler;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@@ -33,7 +33,8 @@ class ManagerRepresentationModelAssembler extends SimpleIdentifiableRepresentati
|
||||
}
|
||||
|
||||
/**
|
||||
* Retain default links provided by {@link SimpleIdentifiableRepresentationModelAssembler}, but add extra ones to each {@link Manager}.
|
||||
* Retain default links provided by {@link SimpleIdentifiableRepresentationModelAssembler}, but add extra ones to each
|
||||
* {@link Manager}.
|
||||
*
|
||||
* @param resource
|
||||
*/
|
||||
@@ -44,11 +45,11 @@ class ManagerRepresentationModelAssembler extends SimpleIdentifiableRepresentati
|
||||
*/
|
||||
super.addLinks(resource);
|
||||
|
||||
resource.getContent().getId()
|
||||
.ifPresent(id -> {
|
||||
// Add custom link to find all managed employees
|
||||
resource.add(linkTo(methodOn(EmployeeController.class).findEmployees(id)).withRel("employees"));
|
||||
});
|
||||
resource.getContent().getId() //
|
||||
.ifPresent(id -> { //
|
||||
// Add custom link to find all managed employees
|
||||
resource.add(linkTo(methodOn(EmployeeController.class).findEmployees(id)).withRel("employees"));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -35,7 +35,8 @@ class RootController {
|
||||
|
||||
resourceSupport.add(linkTo(methodOn(RootController.class).root()).withSelfRel());
|
||||
resourceSupport.add(linkTo(methodOn(EmployeeController.class).findAll()).withRel("employees"));
|
||||
resourceSupport.add(linkTo(methodOn(EmployeeController.class).findAllDetailedEmployees()).withRel("detailedEmployees"));
|
||||
resourceSupport
|
||||
.add(linkTo(methodOn(EmployeeController.class).findAllDetailedEmployees()).withRel("detailedEmployees"));
|
||||
resourceSupport.add(linkTo(methodOn(ManagerController.class).findAll()).withRel("managers"));
|
||||
|
||||
return ResponseEntity.ok(resourceSupport);
|
||||
|
||||
@@ -30,16 +30,15 @@ import com.fasterxml.jackson.annotation.JsonPropertyOrder;
|
||||
* @author Greg Turnquist
|
||||
*/
|
||||
@Value
|
||||
@JsonPropertyOrder({"id", "name", "employees"})
|
||||
@JsonPropertyOrder({ "id", "name", "employees" })
|
||||
class Supervisor {
|
||||
|
||||
@JsonIgnore
|
||||
private final Manager manager;
|
||||
@JsonIgnore private final Manager manager;
|
||||
|
||||
public Long getId() {
|
||||
|
||||
return this.manager.getId()
|
||||
.orElseThrow(() -> new RuntimeException("Couldn't find anything"));
|
||||
return this.manager.getId() //
|
||||
.orElseThrow(() -> new RuntimeException("Couldn't find anything"));
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
@@ -47,8 +46,9 @@ class Supervisor {
|
||||
}
|
||||
|
||||
public List<String> getEmployees() {
|
||||
return manager.getEmployees().stream()
|
||||
.map(employee -> employee.getName() + "::" + employee.getRole())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return manager.getEmployees().stream() //
|
||||
.map(employee -> employee.getName() + "::" + employee.getRole()) //
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,8 +22,8 @@ import org.springframework.web.bind.annotation.PathVariable;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
/**
|
||||
* Represent an older controller that has since been replaced with {@link ManagerController}.
|
||||
* This controller is used to provide legacy routes, i.e. backwards compatibility.
|
||||
* Represent an older controller that has since been replaced with {@link ManagerController}. This controller is used to
|
||||
* provide legacy routes, i.e. backwards compatibility.
|
||||
*
|
||||
* @author Greg Turnquist
|
||||
*/
|
||||
@@ -40,9 +40,10 @@ public class SupervisorController {
|
||||
public ResponseEntity<EntityModel<Supervisor>> findOne(@PathVariable Long id) {
|
||||
|
||||
EntityModel<Manager> managerResource = controller.findOne(id).getBody();
|
||||
EntityModel<Supervisor> supervisorResource = new EntityModel<>(
|
||||
new Supervisor(managerResource.getContent()),
|
||||
managerResource.getLinks());
|
||||
|
||||
EntityModel<Supervisor> supervisorResource = new EntityModel<>( //
|
||||
new Supervisor(managerResource.getContent()), //
|
||||
managerResource.getLinks());
|
||||
|
||||
return ResponseEntity.ok(supervisorResource);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user