Skip to main content

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 typeMethod
@GetMappingGET
@PostMappingPOST
@PutMappingPUT
@DeleteMappingDELETE
@PatchMappingPATCH

@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​

  1. Create a custom error response class
public class StudentErrorResponse {

private int status;
private String message;
private long timeStamp;

// constructors
// getters / setters
}
  1. Create a custom exception class
public class StudentNotFoundException extends RuntimeException {

public StudentNotFoundException(String message) {
super(message);
}
}
  1. 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);
}
  1. 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 MethodEndpointCRUD Action
POST/api/employeesCreate a new one
GET/api/employeesRead a list of
GET/api/employees/{employeeId}Read a single
PUT/api/employeesUpdate 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 and primary 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​

  1. Your entity: Employee
  2. JpaRepository: EmployeeRepository extends JpaRepository
  3. 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​

AnnotationMeaning
@Componentgeneric stereotype for any Spring-managed component
@Repositorystereotype for persistence layer
@Servicestereotype for service layer
@Controllerstereotype for presentation layer (spring-mvc)