Hands-On RESTful API Design Patterns and Best Practices
上QQ阅读APP看书,第一时间看更新

Statelessness

Statelessness refers to servers being free from application states, that is, the states that are stored at the server side and help to identify the client's requests, client's last interaction details, and their current context information.

The REST architecture enforces the server not to maintain any client states at the server side and insists on statelessness between the server and the calling client. Any API developer certainly does not want to store state information at the application server side. So, the application server should always be designed as state-free (in most cases).

Let's observe a few responsibilities for both the client and server so that we can achieve statelessness:

 

To comply with RESTful constraints, and for the service to be genuinely stateless, the servers don't even store the authentication/authorization information of the client and make clients provide credentials with their request. So, each request is understood separately by the server and there is no impact on the current request due to previous requests from the same clients.

In our chapter code example, we can observe that none of our requests and responses are associated with/carry any state information and they are entirely independent. Even in later sections when we will develop authentication examples, our code will still evolve and maintain statelessness across its life cycle.

For stateless constraints, how do we code? Spring Boot's REST API framework provides out-of-the-box implementation; our responsibility as a developer is to ensure we follow URI constraints and provide the necessary implementation for the URI. In the following code snippet from our example, InvestorController.java, we have a URI (/investors/{investorId}/stocks ) defined for fetching the stock of an investor by the investor ID; that's all—we do not have any specific implementation, session validation, and so on:

@GetMapping(path = "/investors/{investorId}/stocks")
public List<Stock> fetchStocksByInvestorId(@PathVariable String investorId,
@RequestParam(value = "offset", defaultValue = "0") int offset,
@RequestParam(value = "limit", defaultValue = "5") int limit) {
return investorService.fetchStocksByInvestorId(investorId, offset, limit);
}

As the path element doesn't have any indications of state, and the code expects an investorId along with a few other parameters, our implementation is fulfilling the stateless constraints. This will be more interesting when we deal with authentication (also with statelessness) in the next chapter.

Let's also observe the necessities and a few advantages of enforcing statelessness in RESTful services through the following table: