-
Notifications
You must be signed in to change notification settings - Fork 41.6k
Description
Before reading, i don't know, for whatever reason the GIT editor removes the Angle brackets. it should be Optional of "Employee" in the code examples.
I believe Spring Boot should provide implicit propagation of Optional types from the Repository layer to the Service layer and then to the Controller layer, without the need to explicitly define the return type in the Service and Controller methods.
// Repository
public interface EmployeeRepository extends JpaRepository<Employee, Integer> {
public Optional<Employee> findByName(String name);
}
// Service
public Optional<Employee> getEmployeeByName(String name) {
public Optional<Employee> getEmployeeByName(String name){
return Optional.ofNullable(employeeRepository.findByName(name).orElseThrow(() -> new EmployeeNotFoundException("Employee with Name " + name + " not found.")));
}
// Controller
@GetMapping("/{name}")
public Optional<Employee> getEmployeeByName(@PathVariable String name) throws EmployeeNotFoundException {
return employeeService.getEmployeeByName(name);
}
The findByName method in the Repository returns an Optional. However, in the Service layer, we need to explicitly wrap the result in an Optional again using map or Optional.ofNullable. Similarly, in the Controller layer, we need to return an Optional.
It would be more intuitive and less verbose if Spring Boot could automatically propagate the Optional type from the Repository to the Service and Controller layers without requiring explicit wrapping. This could be achieved by:
- Introducing a configuration option to enable implicit Optional propagation, e.g., @EnableOptionalPropagation at the application level.
- Modifying the Spring MVC and Spring Data JPA components to automatically handle Optional return types from Repository and Service methods.
- Providing a default behavior where an empty Optional is automatically converted to a 404 Not Found response in the Controller.
With this change, the code could be simplified to:
// Repository
public interface EmployeeRepository extends JpaRepository<Employee, Integer> {
public Optional<Employee> findByName(String name);
}
// Service
public Optional<Employee> getEmployeeByName(String name) {
return employeeRepository.findByName(name)
.orElseThrow(() -> new EmployeeNotFoundException("Employee with Name " + name + " not found."));
}
// Controller
@GetMapping("/{name}")
public Employee getEmployeeByName(@PathVariable String name) throws EmployeeNotFoundException {
return employeeService.getEmployeeByName(name).get();
}
PS: When doing so at the Service Layer, the following error shows up :
Required type: Optional <com.xxx.exceptions.model.Employee>
Provided: Employee
and it suggests to wrap it in an Optional.
In this updated version:
The Service method can directly return the Optional from the Repository without any wrapping.
The Controller method can directly return the Employee object from the Optional (assuming a non-empty Optional). If the Optional is empty, Spring will automatically handle it as a 404 response.
This implicit propagation of Optional would make the code more concise, readable, and consistent with the original intent of the Optional type. It would also reduce boilerplate code and potential errors caused by forgetting to handle Optional types correctly in the Service and Controller layers.
I believe this feature would greatly improve the developer experience when working with Optional types in Spring Boot applications. Please consider adding support for implicit Optional propagation in an upcoming release of Spring Boot.