Module 3 - Creating RESTful Web Services


Conceptual Overview

What is REST?

REST (Representational State Transfer) is an architectural style for designing networked applications. The key principles that define a RESTful system include:

  1. Client-Server Architecture: Separation of concerns between the client (user interface) and server (data storage)
  2. Statelessness: Each request contains all the information needed to complete it
  3. Cacheability: Responses must define themselves as cacheable or non-cacheable
  4. Uniform Interface: Resources are identified by URIs, and interactions happen through standard HTTP methods
  5. Layered System: A client cannot tell whether it’s connected directly to the end server or to an intermediary
  6. Code on Demand (optional): Servers can temporarily extend client functionality by transferring executable code

HTTP Methods in RESTful APIs

REST APIs leverage HTTP methods to perform operations on resources:

HTTP Method Purpose Idempotent? Safe?
GET Retrieve resource(s) Yes Yes
POST Create a new resource No No
PUT Update a resource (complete replacement) Yes No
PATCH Partial update of a resource Yes No
DELETE Remove a resource Yes No

Idempotent: Multiple identical requests have the same effect as a single request Safe: Operation doesn’t alter the state of the server

RESTful Resource Naming

Good practices for resource naming include:

  • Use nouns, not verbs (/books not /getBooks)
  • Use plural nouns for collections (/books instead of /book)
  • Use hierarchical relationships (/authors/123/books)
  • Use hyphens for word separation (/book-reviews not /book_reviews or /bookReviews)

Spring Boot REST Fundamentals

Spring Boot provides excellent support for building RESTful APIs through:

  1. @RestController: Combines @Controller and @ResponseBody annotations, indicating that method returns are directly written to the response body, not resolved as view names
  2. @RequestMapping: Specifies the base URL path for controller methods
  3. @GetMapping, @PostMapping, etc.: Shortcuts for HTTP method-specific mappings
  4. @PathVariable: Extracts values from the URI path
  5. @RequestParam: Extracts values from query parameters
  6. @RequestBody: Binds request body to a method parameter
  7. ResponseEntity: Provides complete control over the HTTP response, including status codes and headers

HTTP Status Codes

Proper status code selection is crucial for RESTful services:

  • 2xx Success

    • 200 OK: Standard success
    • 201 Created: Resource successfully created
    • 204 No Content: Success but no response body
  • 4xx Client Error

    • 400 Bad Request: Malformed request syntax
    • 401 Unauthorized: Authentication required
    • 403 Forbidden: Valid credentials but insufficient permissions
    • 404 Not Found: Resource doesn’t exist
    • 405 Method Not Allowed: Valid resource but HTTP method not supported
  • 5xx Server Error

    • 500 Internal Server Error: Generic server error
    • 502 Bad Gateway: Invalid response from upstream server
    • 503 Service Unavailable: Server temporarily unavailable

API Documentation with Spring Boot

Spring Boot integrates with OpenAPI (formerly Swagger) for API documentation:

  1. SpringDoc library automates the generation of API documentation
  2. Swagger UI provides an interactive interface to explore and test the API
  3. OpenAPI Specification produces a machine-readable description of your API

Monitoring with Spring Boot Actuator

Spring Boot Actuator provides production-ready features to monitor and manage applications:

  1. Endpoints: Pre-defined endpoints exposing operational information
  2. Health checks: Indicators of application health
  3. Metrics: Application performance and resource consumption data
  4. Auditing: Tracking security-related events

Lecture: Creating RESTful APIs with Spring Boot

Introduction to REST Controllers

In Spring Boot, REST controllers are defined using the @RestController annotation:

@RestController
@RequestMapping("/api/books")
public class BookController {
    // Controller methods go here
}

Unlike traditional MVC controllers, REST controllers automatically serialize returned objects to JSON (or XML), eliminating the need for a separate view layer.

Handling Different HTTP Methods

Each HTTP method corresponds to a specific operation on resources:

// GET /api/books
@GetMapping
public List<Book> getAllBooks() {
    return bookService.findAll();
}

// GET /api/books/123
@GetMapping("/{id}")
public Book getBookById(@PathVariable Long id) {
    return bookService.findById(id);
}

// POST /api/books
@PostMapping
public ResponseEntity<Book> createBook(@RequestBody Book book) {
    Book savedBook = bookService.save(book);
    return ResponseEntity.status(HttpStatus.CREATED).body(savedBook);
}

// PUT /api/books/123
@PutMapping("/{id}")
public ResponseEntity<Book> updateBook(@PathVariable Long id, @RequestBody Book book) {
    Book updatedBook = bookService.update(id, book);
    return ResponseEntity.ok(updatedBook);
}

// DELETE /api/books/123
@DeleteMapping("/{id}")
public ResponseEntity<Void> deleteBook(@PathVariable Long id) {
    bookService.delete(id);
    return ResponseEntity.noContent().build();
}

Request Validation

Spring Boot integrates with Bean Validation (JSR-380) to validate incoming requests:

@PostMapping
public ResponseEntity<Book> createBook(@Valid @RequestBody Book book) {
    Book savedBook = bookService.save(book);
    return ResponseEntity.status(HttpStatus.CREATED).body(savedBook);
}

The @Valid annotation triggers validation of the request body. Validation constraints are defined in the model class:

public class Book {
    @NotBlank(message = "Title cannot be blank")
    private String title;

    @NotBlank(message = "Author cannot be blank")
    private String author;

    @Min(value = 1, message = "Page count must be greater than 0")
    private int pageCount;

    // getters and setters
}

Error Handling

In RESTful applications, error handling should be consistent and follow API conventions:

@RestControllerAdvice
public class RestExceptionHandler {

    @ExceptionHandler(ResourceNotFoundException.class)
    public ResponseEntity<ErrorResponse> handleResourceNotFound(ResourceNotFoundException ex) {
        ErrorResponse error = new ErrorResponse(
            HttpStatus.NOT_FOUND.value(),
            ex.getMessage(),
            System.currentTimeMillis()
        );
        return new ResponseEntity<>(error, HttpStatus.NOT_FOUND);
    }

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<ErrorResponse> handleValidationExceptions(MethodArgumentNotValidException ex) {
        List<String> errors = ex.getBindingResult()
            .getAllErrors()
            .stream()
            .map(DefaultMessageSourceResolvable::getDefaultMessage)
            .collect(Collectors.toList());

        ErrorResponse error = new ErrorResponse(
            HttpStatus.BAD_REQUEST.value(),
            "Validation failed",
            System.currentTimeMillis(),
            errors
        );

        return new ResponseEntity<>(error, HttpStatus.BAD_REQUEST);
    }
}

Testing REST Controllers

Spring Boot provides excellent support for testing REST controllers:

@SpringBootTest
@AutoConfigureMockMvc
public class BookControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private BookService bookService;

    @Test
    public void testGetAllBooks() throws Exception {
        List<Book> books = Arrays.asList(
            new Book(1L, "Clean Code", "Robert Martin", 464),
            new Book(2L, "Effective Java", "Joshua Bloch", 416)
        );

        when(bookService.findAll()).thenReturn(books);

        mockMvc.perform(get("/api/books"))
            .andExpect(status().isOk())
            .andExpect(jsonPath("$", hasSize(2)))
            .andExpect(jsonPath("$[0].title", is("Clean Code")))
            .andExpect(jsonPath("$[1].title", is("Effective Java")));
    }
}

Spring Boot Actuator

Spring Boot Actuator adds production-ready features to your application:

# Add to application.properties
management.endpoints.web.exposure.include=health,info,metrics
management.endpoint.health.show-details=always

With these settings, you can access:

  • /actuator/health: Application health information
  • /actuator/info: Application information
  • /actuator/metrics: Application metrics

API Documentation with SpringDoc

To add OpenAPI documentation:

  1. Add the SpringDoc dependency:
<dependency>
    <groupId>org.springdoc</groupId>
    <artifactId>springdoc-openapi-ui</artifactId>
    <version>1.7.0</version>
</dependency>
  1. Configure the OpenAPI info:
@Configuration
public class OpenApiConfig {
    @Bean
    public OpenAPI customOpenAPI() {
        return new OpenAPI()
            .info(new Info()
                .title("Book Catalog API")
                .version("1.0")
                .description("A simple Book Catalog API"));
    }
}
  1. Enhance controllers and models with OpenAPI annotations:
@Operation(summary = "Get all books", description = "Returns a list of all books in the catalog")
@ApiResponses(value = {
    @ApiResponse(responseCode = "200", description = "Successfully retrieved books")
})
@GetMapping
public List<Book> getAllBooks() {
    return bookService.findAll();
}

With this configuration, you can access the Swagger UI at /swagger-ui.html.

Quiz: RESTful Web Services

  1. What does REST stand for? a) Representational State Transfer b) Remote Service Technology c) Responsive System Transfer d) Remote State Transfer

  2. Which HTTP method should be used to retrieve a resource without modifying it? a) POST b) GET c) PUT d) DELETE

  3. Which HTTP status code is most appropriate for a successful resource creation? a) 200 OK b) 201 Created c) 202 Accepted d) 204 No Content

  4. In Spring Boot, which annotation combines @Controller and @ResponseBody? a) @ApiController b) @WebController c) @RestController d) @HttpController

  5. Which annotation is used to extract values from the URI path in Spring Boot? a) @PathVariable b) @PathParam c) @UriParam d) @RequestPath

  6. Which is NOT a characteristic of a RESTful service? a) Statelessness b) Uniform interface c) Client-server architecture d) Session management

  7. To validate a request body in Spring Boot, which annotation is used? a) @Validate b) @Valid c) @RequestValidation d) @Validated

  8. Which Spring Boot starter is used to add monitoring and management capabilities? a) spring-boot-starter-monitor b) spring-boot-starter-management c) spring-boot-starter-actuator d) spring-boot-starter-admin

  9. Which HTTP method is idempotent? a) GET b) POST c) Both a and b d) Neither a nor b

  10. In a RESTful API, what is the recommended way to name resources? a) Use verbs like /getBooks b) Use singular nouns like /book c) Use plural nouns like /books d) Use camelCase like /getBookByAuthor


Quiz Answers

  1. What does REST stand for? Answer: a) Representational State Transfer

  2. Which HTTP method should be used to retrieve a resource without modifying it? Answer: b) GET

  3. Which HTTP status code is most appropriate for a successful resource creation? Answer: b) 201 Created

  4. In Spring Boot, which annotation combines @Controller and @ResponseBody? Answer: c) @RestController

  5. Which annotation is used to extract values from the URI path in Spring Boot? Answer: a) @PathVariable

  6. Which is NOT a characteristic of a RESTful service? Answer: d) Session management

  7. To validate a request body in Spring Boot, which annotation is used? Answer: b) @Valid

  8. Which Spring Boot starter is used to add monitoring and management capabilities? Answer: c) spring-boot-starter-actuator

  9. Which HTTP method is idempotent? Answer: a) GET

  10. In a RESTful API, what is the recommended way to name resources? Answer: c) Use plural nouns like /books


By Wahid Hamdi