Polishing.

This commit is contained in:
Greg Turnquist
2019-03-03 11:05:27 -06:00
parent 15db5a0513
commit e8de8268ad
40 changed files with 443 additions and 463 deletions

View File

@@ -30,6 +30,7 @@ class DatabaseLoader {
@Bean
CommandLineRunner initDatabase(EmployeeRepository employeeRepository, ManagerRepository managerRepository) {
return args -> {
/*
* Gather Gandalf's team
*/

View File

@@ -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) {

View File

@@ -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());
}
}

View File

@@ -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"));

View File

@@ -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() {

View File

@@ -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"));
}

View File

@@ -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) {

View File

@@ -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)));
}
}

View File

@@ -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"));
});
}
/**

View File

@@ -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);

View File

@@ -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());
}
}

View File

@@ -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);
}