In his talk on Some REST Design Patterns (and Anti-Patterns), Cesare Pautasso explains, “REST architectural style is simple to define, but understanding how to apply it to design concrete REST services in support of SOA can be more complex.”
Several SOA Design Patterns:
- Uniform Contract
- Endpoint Redirection
- Content Negotiation
- Idempotent Capability
In this post, you will learn the design methodology, walk through a step by step scenario where the client and server trade information to perform a set of actions, and you will learn more about the SOA design patterns.
REST Summary
In Choosing Between RESTful Web Service, SOAP, you learned that Representational State Transfer (REST) is an architecture style or design pattern for creating web services which allow anything connected to a network to something else on the network using Hypertext Transfer Protocol (HTTP).
Web Services expose data and functionality through resources identified by a Uniform Resource Identifier (URI).
REST has a uniform interface where clients perform stateless interaction with resources using a fixed set of verbs, typically GET (read), PUT (update), DELETE, POST.
You can have multiple representations of the same data.
Hyperlinks model resource relationships and valid state transitions for dynamic protocol description and discovery.
Design Methodology
You should take steps to define your REST :
- Identify resources to be exposed as services (e.g., yearly risk report, book catalog, purchase order, open bugs, polls and votes)
- Model relationships (e.g., containment, reference, state transitions) between resources with hyperlinks that can be followed to get more details (or perform state transitions)
- Define “nice” URIs to address the resources
- Understand what it means to do a GET, POST, PUT, DELETE for each resource (and whether it is allowed or not)
- Design and document resource representations
- Implement and deploy on Web server
- Test with a Web browser
(Illustrations from SOA2010 SOA with REST)
Although there are four methods, you can add more resources, such as an author. And you can have multiple representations.
Scenario
Let’s create a simple example in a polling scenario.
in our scenario, you have polls and votes. It’s a containment relationship where you have number of polls in which you have a number of votes.
The URIs embed the identifiers of child instance resources.
POST on the container is used to create child resources.
PUT/DELETE us used for updating and removing child resources.
Step 1. Create a poll
In the first step, you create poll. In this case, we will use XML in the body. But you can also use JSON.
https://gist.github.com/devdays/9eb8e3333db655fde8ff
In this case, the poll was created using POST with the possible options that the user could select. The server returns a 201 response with the location of the poll and its identifier.
Step 2. Reading the poll
The client can then send a request to the server to read the poll.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
GET /poll/770115 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
200 OK | |
<options>A,B,C</options> | |
<votes href="vote" /> |
p>The poll with its identifier are retrieved with 200 OK in the response. The response body includes the options and the reference for the votes.
Step 3. Vote in a particular poll
In this step, you would post the data and return that the data vote was created. The response includes the location of the vote.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
201 Created | |
Location: /poll/770115/vote/1 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
POST /poll/770115/vote | |
<name>Bruce Kyle</name> | |
<choice>C</choice> |
Step 4. Retrieve votes
You can then retrieve the votes.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
GET /poll/770115 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
200 OK | |
<options>A,B,C<options> | |
<votes> | |
<vote id="1"> | |
<name>Bruce Kyle</name> | |
<choice>C</choice> | |
</vote> | |
</votes> |
Step 5. Update a particular vote
You can now let your user change their mind. In this case, use a PUT to update the particular vote. Note that the URI goes to vote/1.
https://gist.github.com/devdays/c73925dbe98695ae7d6
Step 6. Retrieve
You can then retrieve the poll results again.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
GET /poll/770115 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
200 OK | |
<options>A,B,C<options> | |
<votes> | |
<vote id="1"> | |
<name>Bruce Kyle</name> | |
<choice>A</choice | |
</vote> | |
</votes> |
Step 7. Delete the Poll
You can then use the DELETE verb to delete the poll.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
DELETE /poll/770115 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
200 OK |
Step 8. Retrieve a poll that has been deleted
The server returns an 404 Not Found error because the poll has been deleted.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
GET /poll/770115 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
404 Not Found |
Uniform Contract
How can consumers take advantage of multiple evolving endpoints? You need to keep your consumer up to date with respect to evolving contracts.
In the previous example, you saw how a Uniform Contract provides for Create, Read, Update, and Delete.
CRUD |
HTTP |
|
CREATE | POST | Create a sub resource |
READ | GET | Retrieve the current state of the resource |
UPDATE | PUT | Initialize or update the state of the resource for a given URI |
DELETE | DELETE | Clear a resource, after the URI is no longer valid |
POST vs GET
GET is a read-only operation. It can be repeated without affecting the state of the resource and can be cached.
NOTE: This does not mean that the same representation will be returned every time.
POST is a read-write operation and may change the state of the resource and provoke side effects on the server.
POST vs POST
How should you create a resource?
Solution 1. Let the client choose a unique ID
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
PUT /resource/E809EF63-86D7-4B8B-973E-69C1B509F692 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
201 Created |
The downside of this is that how are you sure the client creates a unique identifier?
Solution 2. Let the server compute the unique id
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
POST /resource |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
301 Moved Permanently | |
Location: /resource/E809EF63-86D7-4B8B-973E-69C1B509F692 |
The downside of this is that duplicate instances can be created if requests are repeated due to communication issues.
Endpoint Redirection
How do you provide the consumer with information so they can adapt to changes in your service. For example, you may want to change the structure of your data. It may not be possible to replace all of your old endpoints simultaneously.
In that case, you can automatically refer your consumers that access the stale endpoint to the current identifier.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
GET /old |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
301 Moved Permanently | |
Location: /new |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
GET /new |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
200 OK |
HTTP supported endpoint redirection using a combination of the 3xx status codes and standard headers. For example, instead of using 301, you could provide 307 Temporary Redirect:
307 Temporary Redirect Location: /newUri
Entity Endpoint
How can service consumers support new consumers without changing their contract? How can you change the content and data representation formats?
You want your Web Service to provide for loose coupling, increased interoperability, and increased organizational agility.
You can allow the client to negotiate the message format in a single message. The client can list the set of understood formats (MIME types). Then the server chooses the most appropriate and send the reply (or a 406 error if none can be found.)
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
GET /resource | |
Accept: text/html, application/xml, application/json |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
200 OK | |
Content-Type: application/json |
You can perform content negotiation across different dimensions.
Request Header |
Example Values |
Response Header |
Accept: | application/xml, application/json |
Content-Type: |
Accept-Language: | en, fr, de, es | Content-Language: |
Accept-Charset: | iso-8859-5, unicode-1-1 |
Charset parameter of the Content-Type header |
Accept-Encoding: | compress, gzip | Content-Encoding |
Additional REST Patterns
- Entity Linking
- Distributed Response Caching
- Idempotent Capacity
- Message-based State Deferral
- Message-based Logic Deferral
- Consumer-Processed Composition
For more patterns, see SOAPatterns.org.
References
Slideshare: SOA with REST