Rest API
Web starter is requiredβ
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
Rest controllerβ
@RequestMapping
is needed at the class level to express shared mappings
Mapping type | Method |
---|---|
@GetMapping | GET |
@PostMapping | POST |
@PutMapping | PUT |
@DeleteMapping | DELETE |
@PatchMapping | PATCH |
@RestController
@RequestMapping("/test")
public class DemoRestController {
@GetMapping("/hello")
public String sayHello() {
return "Hello World!";
}
}
Serializationβ
- Spring uses the Jackson Project behind the scenes
- By default, Jackson will call appropriate getter/setter method
Path Variablesβ
We can bind path variable to method parameter using @PathVariable
@GetMapping("/students/{studentId}")
public Student getStudent(@PathVariable int studentId) {
}
Exception Handlingβ
- Create a custom error response class
public class StudentErrorResponse {
private int status;
private String message;
private long timeStamp;
// constructors
// getters / setters
}
- Create a custom exception class
public class StudentNotFoundException extends RuntimeException {
public StudentNotFoundException(String message) {
super(message);
}
}
- Update REST service to throw exception if student not found
@GetMapping("/students/{studentId}")
public Student getStudent(@PathVariable int studentId) {
if ((studentId >= theStudents.size()) || (studentId < 0)) {
throw new StudentNotFoundException("Student id not found - " + studentId);
}
return theStudents.get(studentId);
}
- Add an exception handler method using @ExceptionHandler
@ExceptionHandler
public ResponseEntity<StudentErrorResponse> handleException(StudentNotFoundException exc) {
StudentErrorResponse error = new StudentErrorResponse();
error.setStatus(HttpStatus.NOT_FOUND.value());
error.setMessage(exc.getMessage());
error.setTimeStamp(System.currentTimeMillis());
return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
}
Global Exception Handlingβ
@ControllerAdvice
β
- Pre-process requests to controllers
- Post-process responses to handle exceptions
@ControllerAdvice
public class StudentRestExceptionHandler {
@ExceptionHandler
public ResponseEntity<StudentErrorResponse> handleException(StudentNotFoundException exc) {
StudentErrorResponse error = new StudentErrorResponse();
error.setStatus(HttpStatus.NOT_FOUND.value());
error.setMessage(exc.getMessage());
error.setTimeStamp(System.currentTimeMillis());
return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
}
}
Rest service exampleβ
HTTP Method | Endpoint | CRUD Action |
---|---|---|
POST | /api/employees | Create a new one |
GET | /api/employees | Read a list of |
GET | /api/employees/{employeeId} | Read a single |
PUT | /api/employees | Update an existing |
DELETE | /api/employees/{employeeId} | Delete an existing |
@Service
β
Purpose of Service Layerβ
- Service Facade design pattern
- Intermediate layer for custom business logic
- Integrate data from multiple sources (DAO/repositories)
@Service
public class EmployeeServiceImpl implements EmployeeService {
// inject EmployeeDAO ...
@Override
public List<Employee> findAll() {
return employeeDAO.findAll();
}
}
Service Layer - Best Practiceβ
- Apply transactional boundaries at the service layer
- It is the service layerβs responsibility to manage transaction boundaries
- For implementation code
- Apply @Transactional on service methods
- Remove @Transactional on DAO methods if they already exist
Spring Data JPAβ
- Create a DAO and just plug in your
entity type
andprimary key
- Spring will give you a CRUD implementation
- To do this our DAO should implement JpaRepository interface
public interface EmployeeRepository extends JpaRepository<Employee, Integer> {
// that's it :)
}
Advanced features availableβ
- Extending and adding custom queries with JPQL
- Query Domain Specific Language (Query DSL)
- Defining custom methods (low-level coding)
Spring Data RESTβ
- Leverages your existing JpaRepository
- Spring will give you a REST CRUD implementation
- Spring Data REST will scan your project for JpaRepository
- Expose REST APIs for each entity type for your JpaRepository
- By default, Spring Data REST will create endpoints based on entity type
- First character of Entity type is lowercase
- adds an "s" to the entity
- Just add Spring Data REST to your Maven POM file
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-rest</artifactId>
</dependency>
For Spring Data REST we needβ
- Your entity:
Employee
- JpaRepository:
EmployeeRepository extends JpaRepository
- Maven POM dependency for:
spring-boot-starter-data-rest
Spring Data REST advanced featuresβ
- Pagination, sorting and searching
- Extending and adding custom queries with JPQL Query Domain Specific Language (Query DSL)
@RepositoryRestResource
β
Specify plural name / path with an annotation
@RepositoryRestResource(path = "members")
public interface EmployeeRepository extends JpaRepository<Employee, Integer> {
}
Different components covered so farβ
Annotation | Meaning |
---|---|
@Component | generic stereotype for any Spring-managed component |
@Repository | stereotype for persistence layer |
@Service | stereotype for service layer |
@Controller | stereotype for presentation layer (spring-mvc) |