REST

REST

Representational State Transfer, or REST, is an architectural style for systems that communicate over the Web. It is not a protocol and it is not a library. REST uses HTTP’s concepts to give an API a predictable interface.

The central idea is the resource. A resource is a thing the application makes available to clients: a product, an order, a user, or a collection of products. It is identified by a URL.

/api/products
/api/products/42
/api/orders/18

A resource is not necessarily a database row. For example, /api/reports/sales can represent a report calculated from several tables and external services. The client receives a representation of the resource, commonly JSON, rather than direct access to the application’s internal objects.

Designing resource URLs

URLs should identify resources, while HTTP methods should identify the operation. For this reason, REST APIs usually use nouns in paths rather than verbs.

GET    /api/products        List products
POST   /api/products        Create a product
GET    /api/products/42     Retrieve product 42
PUT    /api/products/42     Replace product 42
DELETE /api/products/42     Delete product 42

/api/products/42 identifies one product whatever the method is. This is more consistent than URLs such as /api/getProduct?id=42 or /api/deleteProduct/42. The method already describes what the client wants to do.

Collections use plural nouns, such as /api/products. An item in a collection is addressed with its identifier, such as /api/products/42. Query parameters refine a request without changing the resource hierarchy.

GET /api/products?category=keyboards&page=2&size=20

This request asks for a page of products in the keyboards category.

Stateless requests

A RESTful interaction is stateless: each request contains all the information the server needs to process it. The server does not need to remember a previous request from the same client to understand the next one.

For example, a client includes its access token on every request that needs authentication.

GET /api/products HTTP/1.1
Authorization: Bearer eyJhbGciOiJIUzI1NiJ9

Statelessness makes an API easier to scale because any server instance can process a request. It does not mean that the application stores no data. Products, orders, and user accounts are still stored by the application; the server simply does not rely on hidden conversation state between requests.

REST with Spring Web

Spring Web maps HTTP requests to Java methods. @RestController marks a class whose methods write their return values to the HTTP response body. @RequestMapping defines the common URL for the class.

 1import org.springframework.http.HttpStatus;
 2import org.springframework.web.bind.annotation.DeleteMapping;
 3import org.springframework.web.bind.annotation.GetMapping;
 4import org.springframework.web.bind.annotation.PathVariable;
 5import org.springframework.web.bind.annotation.PostMapping;
 6import org.springframework.web.bind.annotation.RequestBody;
 7import org.springframework.web.bind.annotation.RequestMapping;
 8import org.springframework.web.bind.annotation.RequestParam;
 9import org.springframework.web.bind.annotation.ResponseStatus;
10import org.springframework.web.bind.annotation.RestController;
11
12import java.util.List;
13
14@RestController
15@RequestMapping("/api/products")
16class ProductController {
17
18    @GetMapping
19    List<Product> getProducts(@RequestParam(required = false) String category) {
20        return List.of();
21    }
22
23    @GetMapping("/{id}")
24    Product getProduct(@PathVariable Long id) {
25        return new Product(id, "Wireless keyboard");
26    }
27
28    @PostMapping
29    @ResponseStatus(HttpStatus.CREATED)
30    Product createProduct(@RequestBody Product product) {
31        return product;
32    }
33
34    @DeleteMapping("/{id}")
35    @ResponseStatus(HttpStatus.NO_CONTENT)
36    void deleteProduct(@PathVariable Long id) {
37    }
38
39}

@GetMapping, @PostMapping, and @DeleteMapping select the HTTP method. @PathVariable reads a value from the URL path, while @RequestParam reads a query parameter. @RequestBody asks Spring Boot to deserialize the request body into a Java object.

By default, Spring Boot serializes the Java object returned by a controller method as JSON and selects 200 OK as the status. @ResponseStatus changes the successful status when another response is more appropriate. For responses that also need headers, such as the Location header after creating a resource, use ResponseEntity as seen in the first application.

The next section explains how Spring constructs controllers and the other components that make up an application.