- Option 1: Pagination
- Options 2 and 3: Wish List, Wish Template
- Options 4 and 5: Conditional Request, Request Bundle
- Decision Drivers and Tradeoffs
Options 4 and 5: Conditional Request, Request Bundle
Let us consider another situation in which an analysis of the usage of the operations of an API provider shows that some clients keep requesting the same server-side data. The requested data changes much less frequently than the clients send their requests. In such cases, we can avoid unnecessary data transfers with CONDITIONAL REQUESTs.
Pattern: CONDITIONAL REQUEST | |
Problem | How can unnecessary server-side processing and bandwidth usage be avoided when frequently invoking API operations that return rarely changing data? |
Solution | Make requests conditional by adding METADATA ELEMENTS to their message representations (or protocol headers) and processing these requests only if the condition specified by the metadata is met. |
For example, the provider could supply a fingerprint for each resource accessed, which the client caches locally along with the data. This fingerprint can then be included in a subsequent request to indicate which "version" of the data it already so that only newer versions are sent. The following figure illustrates the solution elements:
Click to view full-sized image
Different conditions and types of fingerprint exist, for example, version numbers, hash codes or timestamps are variants and applications of the pattern.
In other situations, an analysis of the usage of the already-deployed API might reveal that clients are issuing many similar, but independent requests for which individual responses are returned. These batches of requests may hurt scalability and throughput. In such situations, the REQUEST BUNDLE pattern is eligible.
Pattern: REQUEST BUNDLE | |
Problem | How can the number of requests and responses be reduced to increase communication efficiency? |
Solution | Define a REQUEST BUNDLE as a data container that assembles multiple independent requests in a single request message. Add metadata such as identifiers of individual requests and bundle element counters. |
In the Customer Core service of Lakeside Mutual (a case study running through the book, implemented in Java and Spring Boot and openly available on GitHub), clients can request multiple customers from the customer's INFORMATION HOLDER RESOURCE by specifying an ATOMIC PARAMETER LIST of customer ID ELEMENTS. A path parameter serves as a bundle container. A comma (,) separates the bundle elements:
curl -X GET http://localhost:8080/customers/ce4btlyluu,rgpp0wkpec
This will return the two requested customers as DATA ELEMENTS, represented as JSON objects in a bundle-level container array called customers:
{
"customers": [
{
"customerId": "ce4btlyluu",
"firstname": "Robbie",
"lastname": "Davenhall",
"birthday": "1961-08-11T23:00:00.000+0000",
...
"_links": { ... }
},
{
"customerId": "rgpp0wkpec",
"firstname": "Max",
"lastname": "Mustermann",
"birthday": "1989-12-31T23:00:00.000+0000",
...
"_links": { ... }
}
],
"_links": { ... }
}
REQUEST BUNDLE can be seen as an extension of the general "Command" design pattern: each individual request is a command according to terminology from Design Patterns.