Upgrade to Spring Boot 2.3 and related changes.

This commit is contained in:
Greg L. Turnquist
2020-10-20 16:24:26 -05:00
parent 1d12ed185c
commit 5f74daf4bd
13 changed files with 44 additions and 35 deletions

View File

@@ -128,7 +128,7 @@ class EmployeeController {
ResponseEntity<CollectionModel<EntityModel<Employee>>> findAll() {
List<EntityModel<Employee>> employeeResources = StreamSupport.stream(repository.findAll().spliterator(), false)
.map(employee -> new EntityModel<>(employee,
.map(employee -> EntityModel.of(employee,
linkTo(methodOn(EmployeeController.class).findOne(employee.getId())).withSelfRel()
.andAffordance(afford(methodOn(EmployeeController.class).updateEmployee(null, employee.getId())))
.andAffordance(afford(methodOn(EmployeeController.class).deleteEmployee(employee.getId()))),
@@ -136,7 +136,7 @@ class EmployeeController {
))
.collect(Collectors.toList());
return ResponseEntity.ok(new CollectionModel<>(employeeResources,
return ResponseEntity.ok(CollectionModel.of(employeeResources,
linkTo(methodOn(EmployeeController.class).findAll()).withSelfRel()
.andAffordance(afford(methodOn(EmployeeController.class).newEmployee(null)))));
}
@@ -146,7 +146,7 @@ class EmployeeController {
Employee savedEmployee = repository.save(employee);
return new EntityModel<>(savedEmployee,
return EntityModel.of(savedEmployee,
linkTo(methodOn(EmployeeController.class).findOne(savedEmployee.getId())).withSelfRel()
.andAffordance(afford(methodOn(EmployeeController.class).updateEmployee(null, savedEmployee.getId())))
.andAffordance(afford(methodOn(EmployeeController.class).deleteEmployee(savedEmployee.getId()))),
@@ -207,7 +207,7 @@ class EmployeeController {
ResponseEntity<EntityModel<Employee>> findOne(@PathVariable long id) {
return repository.findById(id)
.map(employee -> new EntityModel<>(employee,
.map(employee -> EntityModel.of(employee,
linkTo(methodOn(EmployeeController.class).findOne(employee.getId())).withSelfRel()
.andAffordance(afford(methodOn(EmployeeController.class).updateEmployee(null, employee.getId())))
.andAffordance(afford(methodOn(EmployeeController.class).deleteEmployee(employee.getId()))),
@@ -225,7 +225,7 @@ class EmployeeController {
Employee updatedEmployee = repository.save(employeeToUpdate);
return new EntityModel<>(updatedEmployee,
return EntityModel.of(updatedEmployee,
linkTo(methodOn(EmployeeController.class).findOne(updatedEmployee.getId())).withSelfRel()
.andAffordance(afford(methodOn(EmployeeController.class).updateEmployee(null, updatedEmployee.getId())))
.andAffordance(afford(methodOn(EmployeeController.class).deleteEmployee(updatedEmployee.getId()))),

View File

@@ -52,14 +52,14 @@ class EmployeeController {
ResponseEntity<CollectionModel<EntityModel<Employee>>> findAll() {
List<EntityModel<Employee>> employeeResources = StreamSupport.stream(repository.findAll().spliterator(), false)
.map(employee -> new EntityModel<>(employee,
.map(employee -> EntityModel.of(employee,
linkTo(methodOn(EmployeeController.class).findOne(employee.getId())).withSelfRel()
.andAffordance(afford(methodOn(EmployeeController.class).updateEmployee(null, employee.getId())))
.andAffordance(afford(methodOn(EmployeeController.class).deleteEmployee(employee.getId()))),
linkTo(methodOn(EmployeeController.class).findAll()).withRel("employees")))
.collect(Collectors.toList());
return ResponseEntity.ok(new CollectionModel<>( //
return ResponseEntity.ok(CollectionModel.of( //
employeeResources, //
linkTo(methodOn(EmployeeController.class).findAll()).withSelfRel()
.andAffordance(afford(methodOn(EmployeeController.class).newEmployee(null)))));
@@ -70,7 +70,7 @@ class EmployeeController {
Employee savedEmployee = repository.save(employee);
return new EntityModel<>(savedEmployee,
return EntityModel.of(savedEmployee,
linkTo(methodOn(EmployeeController.class).findOne(savedEmployee.getId())).withSelfRel()
.andAffordance(afford(methodOn(EmployeeController.class).updateEmployee(null, savedEmployee.getId())))
.andAffordance(afford(methodOn(EmployeeController.class).deleteEmployee(savedEmployee.getId()))),
@@ -91,7 +91,7 @@ class EmployeeController {
ResponseEntity<EntityModel<Employee>> findOne(@PathVariable long id) {
return repository.findById(id)
.map(employee -> new EntityModel<>(employee,
.map(employee -> EntityModel.of(employee,
linkTo(methodOn(EmployeeController.class).findOne(employee.getId())).withSelfRel()
.andAffordance(afford(methodOn(EmployeeController.class).updateEmployee(null, employee.getId())))
.andAffordance(afford(methodOn(EmployeeController.class).deleteEmployee(employee.getId()))),
@@ -108,7 +108,7 @@ class EmployeeController {
Employee updatedEmployee = repository.save(employeeToUpdate);
return new EntityModel<>(updatedEmployee,
return EntityModel.of(updatedEmployee,
linkTo(methodOn(EmployeeController.class).findOne(updatedEmployee.getId())).withSelfRel()
.andAffordance(afford(methodOn(EmployeeController.class).updateEmployee(null, updatedEmployee.getId())))
.andAffordance(afford(methodOn(EmployeeController.class).deleteEmployee(updatedEmployee.getId()))),

View File

@@ -189,8 +189,8 @@ public class HomeController {
private final RestTemplate rest;
public HomeController(RestTemplate restTemplate) {
this.rest = restTemplate;
public HomeController(RestTemplateBuilder restTemplateBuilder) {
this.rest = restTemplateBuilder.build();
}
...
}
@@ -202,7 +202,8 @@ service. So in this example, it is hard coded into place.
WARNING: For fault tolerant production systems, hard coded URIs are NOT recommended. Instead, use something like
Spring Cloud Netflix and it's Eureka/Ribbon features to allow https://spring.io/guides/gs/service-registration-and-discovery/[service discovery] and https://spring.io/guides/gs/client-side-load-balancing/[load balanced calls].
Parts of the controller must also perform REST calls, so we request a `RestTemplate` in the constructor call, allowing Spring to provide it.
Parts of the controller must also perform REST calls, so we request a `RestTemplateBuilder` in the constructor call, allowing Spring Boot to provide it.
Having been decorated with the `HypermediaRestTemplateConfigurer`, it has all active media types applied. You are free to further customize things before invoking the `build()` operation that yields a `RestTemplate`.
To construct a listing of all employees, check out the following controller method:

View File

@@ -15,9 +15,10 @@
*/
package org.springframework.hateoas.examples;
import org.springframework.boot.web.client.RestTemplateCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
import org.springframework.hateoas.config.HypermediaRestTemplateConfigurer;
/**
* @author Greg Turnquist
@@ -26,7 +27,9 @@ import org.springframework.web.client.RestTemplate;
public class ClientConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
RestTemplateCustomizer hypermediaRestTemplateCustomizer(HypermediaRestTemplateConfigurer configurer) {
return restTemplate -> {
configurer.registerHypermediaTypes(restTemplate);
};
}
}

View File

@@ -18,6 +18,7 @@ package org.springframework.hateoas.examples;
import java.net.URI;
import java.net.URISyntaxException;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.hateoas.CollectionModel;
import org.springframework.hateoas.EntityModel;
import org.springframework.hateoas.Link;
@@ -41,10 +42,10 @@ public class HomeController {
private static final String REMOTE_SERVICE_ROOT_URI = "http://localhost:9000";
private final RestTemplate rest;
private RestTemplate rest;
public HomeController(RestTemplate restTemplate) {
this.rest = restTemplate;
public HomeController(RestTemplateBuilder restTemplateBuilder) {
this.rest = restTemplateBuilder.build();
}
/**

View File

@@ -15,9 +15,10 @@
*/
package org.springframework.hateoas.examples;
import org.springframework.boot.web.client.RestTemplateCustomizer;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
import org.springframework.hateoas.config.HypermediaRestTemplateConfigurer;
/**
* @author Greg Turnquist
@@ -26,7 +27,9 @@ import org.springframework.web.client.RestTemplate;
public class ClientConfig {
@Bean
public RestTemplate restTemplate() {
return new RestTemplate();
RestTemplateCustomizer hypermediaRestTemplateCustomizer(HypermediaRestTemplateConfigurer configurer) {
return restTemplate -> {
configurer.registerHypermediaTypes(restTemplate);
};
}
}

View File

@@ -18,6 +18,7 @@ package org.springframework.hateoas.examples;
import java.net.URI;
import java.net.URISyntaxException;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.hateoas.CollectionModel;
import org.springframework.hateoas.EntityModel;
import org.springframework.hateoas.Link;
@@ -43,8 +44,8 @@ public class HomeController {
private final RestTemplate rest;
public HomeController(RestTemplate restTemplate) {
this.rest = restTemplate;
public HomeController(RestTemplateBuilder restTemplateBuilder) {
this.rest = restTemplateBuilder.build();
}
/**

View File

@@ -525,7 +525,7 @@ public class SupervisorController {
public ResponseEntity<EntityModel<Supervisor>> findOne(@PathVariable Long id) {
EntityModel<Manager> managerResource = controller.findOne(id).getBody();
EntityModel<Supervisor> supervisorResource = new EntityModel<>(
EntityModel<Supervisor> supervisorResource = EntityModel.of(
new Supervisor(managerResource.getContent()),
managerResource.getLinks());

View File

@@ -89,7 +89,7 @@ class EmployeeController {
Links newLinks = collectionModel.getLinks().merge(Links.MergeMode.REPLACE_BY_REL,
linkTo(methodOn(EmployeeController.class).findEmployees(id)).withSelfRel());
return ResponseEntity.ok(new CollectionModel<>(collectionModel.getContent(), newLinks));
return ResponseEntity.ok(CollectionModel.of(collectionModel.getContent(), newLinks));
}
@GetMapping("/employees/detailed")

View File

@@ -41,7 +41,7 @@ public class SupervisorController {
EntityModel<Manager> managerResource = controller.findOne(id).getBody();
EntityModel<Supervisor> supervisorResource = new EntityModel<>( //
EntityModel<Supervisor> supervisorResource = EntityModel.of( //
new Supervisor(managerResource.getContent()), //
managerResource.getLinks());

View File

@@ -53,7 +53,7 @@
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.2.6.RELEASE</version>
<version>2.3.4.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>

View File

@@ -96,13 +96,13 @@ The route for the https://martinfowler.com/bliki/DDD_Aggregate.html[aggregate ro
ResponseEntity<CollectionModel<EntityModel<Employee>>> findAll() {
List<EntityModel<Employee>> employees = StreamSupport.stream(repository.findAll().spliterator(), false)
.map(employee -> new EntityModel<>(employee,
.map(employee -> EntityModel.of(employee,
linkTo(methodOn(EmployeeController.class).findOne(employee.getId())).withSelfRel(),
linkTo(methodOn(EmployeeController.class).findAll()).withRel("employees")))
.collect(Collectors.toList());
return ResponseEntity.ok(
new CollectionModel<>(employees,
CollectionModel.of(employees,
linkTo(methodOn(EmployeeController.class).findAll()).withSelfRel()));
}
----
@@ -133,7 +133,7 @@ To build a single resource, the `/employees/{id}` route is shown below:
ResponseEntity<EntityModel<Employee>> findOne(@PathVariable long id) {
return repository.findById(id)
.map(employee -> new EntityModel<>(employee,
.map(employee -> EntityModel.of(employee,
linkTo(methodOn(EmployeeController.class).findOne(employee.getId())).withSelfRel(),
linkTo(methodOn(EmployeeController.class).findAll()).withRel("employees")))
.map(ResponseEntity::ok)

View File

@@ -57,13 +57,13 @@ class EmployeeController {
ResponseEntity<CollectionModel<EntityModel<Employee>>> findAll() {
List<EntityModel<Employee>> employees = StreamSupport.stream(repository.findAll().spliterator(), false)
.map(employee -> new EntityModel<>(employee, //
.map(employee -> EntityModel.of(employee, //
linkTo(methodOn(EmployeeController.class).findOne(employee.getId())).withSelfRel(), //
linkTo(methodOn(EmployeeController.class).findAll()).withRel("employees"))) //
.collect(Collectors.toList());
return ResponseEntity.ok( //
new CollectionModel<>(employees, //
CollectionModel.of(employees, //
linkTo(methodOn(EmployeeController.class).findAll()).withSelfRel()));
}
@@ -73,7 +73,7 @@ class EmployeeController {
try {
Employee savedEmployee = repository.save(employee);
EntityModel<Employee> employeeResource = new EntityModel<>(savedEmployee, //
EntityModel<Employee> employeeResource = EntityModel.of(savedEmployee, //
linkTo(methodOn(EmployeeController.class).findOne(savedEmployee.getId())).withSelfRel());
return ResponseEntity //
@@ -94,7 +94,7 @@ class EmployeeController {
ResponseEntity<EntityModel<Employee>> findOne(@PathVariable long id) {
return repository.findById(id) //
.map(employee -> new EntityModel<>(employee, //
.map(employee -> EntityModel.of(employee, //
linkTo(methodOn(EmployeeController.class).findOne(employee.getId())).withSelfRel(), //
linkTo(methodOn(EmployeeController.class).findAll()).withRel("employees"))) //
.map(ResponseEntity::ok) //