13
RESTful Web Services

WHAT’S IN THIS CHAPTER?            

  • What REST is and what it does
  • The six constraints of REST
  • The Richardson Maturity Model of a REST API
  • How to design a RESTful API
  • Demonstrating REST in Action
  • How to implement REST in a Java EE
  • HATEOAS—The highest level in the Richardson Maturity Model

WROX.COM CODE DOWNLOADS FOR THIS CHAPTER

The wrox.com code download for this chapter is found at www.wrox.com/go/projavaeedesignpatterns on the Download Code tab. The code is in the Chapter 13 download and individually named according to the names throughout the chapter.

There is little doubt that you will have heard the term REST. What is less certain is that you will understand exactly what it means and how it is implemented. Many people who know nothing or very little about REST will tell you that your site must be REST “compatible” and that, without REST, your site cannot possibly survive. REST is a buzzword to these people, but for those who know what REST is and what benefits it can offer, it’s much more than just another buzzword. So what does REST really mean, and where does it come from?

REST means REpresentational State Transfer and is an architectural style of representing and transferring data. It consists of a set of six constraints placed on data, components, and their interactions within a distributed hypermedia system (the Internet). It is not tied to a protocol (although in almost all cases it is used with Hypertext Transfer Protocol [HTTP]), and it does not have a World Wide Web Consortium (W3C) standard. It is a set of conventions, styles, and approaches that have been agreed upon over time by use and convention.

The term REST was coined by Roy Fielding in his 2000 doctoral dissertation titled “Architectural Styles and the Design of Network-Based Software Architectures.”1 Since then, the REST concept has been widely adopted by developers and architects such that it has become an integral part of many languages and frameworks. For example, Ruby provides a natural way to use RESTful routes, and the Spring framework provides a simplified way to implement Hypermedia As The Engine Of Application State (HATEOAS), which is level 3 of the Richardson Maturity Model of REST support (more on this later).2

REST is usually referred to as an architectural approach rather than a design pattern. However, REST was developed against common problems faced in enterprise app, which is the same idea behind the design patterns.

WHAT IS REST?

REST means many things to many people, and discussions can become quite theoretical. This chapter discusses it from the perspective of a developer who wants to implement a RESTful application programming interface (API) for a forum site discussing movies.

The most practical way of thinking about REST is as a style for formatting URIs that represents resources (data) your application can provide and resources that it can store. What is meant by resources? In a forum website, you have many resources, such as the site’s users and the users’ posts. These resources are represented by nouns and combined with an HTTP method to form a RESTful uniform resource identifier (URI). For example, you can represent an account resource with the URI /accounts and combine it with the HTTP GET method such that a request to this URI would return all accounts. Likewise, you can represent an identifiable account resource by appending the post’s ID to the URI like so: /accounts/:id. A GET request to this URI returns the details of the account with the given ID. Not only can you get resource representations by using a RESTful URI, you can create resources. To do this, you would create a URI using the HTTP POST method. For example, to create a new account resource, you would send a POST request to the URI /accounts with a payload in the HTTP body containing the data necessary to create the resource.

As you have gathered, a URI represents a resource on a remote server, and the method of requesting the resources (the HTTP method) implies certain actions on that resource.

It is tempting to map HTTP methods to create, retrieve, update, and delete (CRUD) actions (for example, POST to Create and GET to Read).3 However, this is not in the spirit of REST and does not help in the understanding of resource representations. In fact, it’s more akin to a remote procedure call (RPC) pattern implementation, which is at level 0 on the Richardson Maturity Model. You are only interested in implementing REST at the highest level: level 3, please refer to the section, “Richardson Maturity Model of REST API” for full details.

A RESTful API is not about actions; it’s about nouns. These nouns represent resources. So you’ll learn about a post resource, a user resource, and an address resource as opposed to verbs such as getUser, addPost, and deleteAddress. REST is different from simple object access protocol (SOAP) and RPC, which are about the actions you want to perform on the application’s data. In a RESTful sense, you would call a URI with an appropriate HTTP method.

Each resource is identified by a URI. There may be multiple ways to refer to the same resources, so you might be able to access the same resource from different starting points. For example, you can obtain the resource that represents a user by accessing the user directly via the URI GET /users/:id or by going from one user to the list of users who follow that user and then to the user GET /user/:id1/followers/:id1. The representation of the resource is not the actual resource itself; it’s a representation of the resource, and it is perfectly valid for the same resource to be represented in different ways.

The resource representation flow is bidirectional between client and server and represents at least part of the resource state. When that happens, it contains just enough data to create, modify, or delete that resource on the server.

Resource representations are typically JavaScript Object Notation (JSON) or Extensible Markup Language (XML), but they can be any format, including a custom representation.

THE SIX CONSTRAINTS OF REST

According to Roy Fielding’s dissertation, a truly RESTful architecture conforms to all but one of the stated constraints. This group of constraints is called the REST style.

Client-Server

The client-server constraint is based on the separations of concerns principle and defines clearly the separation between the client and the server. The constraint is simple and requires a client to send a request and a server to receive that request. The server may respond to the client’s request.

Uniform Interface

This constraint defines the interface between the client and the server, stating that it should be as generic and simple as possible. You have already learned that a resource is a representation of the data, and the client does not have direct access to the data. This constraint defines how that resource is represented by nouns and that the interface is maintained by the creator of the actual data system. This is to ensure some degree of constancy of the interfaces over time. The constraint does not specify that the implementation should use the HTTP protocol, but it is almost always based on HTTP. As you have already seen, if you use the HTTP specification, the URI is constructed from the resource nouns and the HTTP verbs.

Stateless

The server should not maintain client state. In other words, each message/request is self-descriptive; it has enough information or context for the server to process that message. This implies that if there is state, it is maintained on the client side. The advantage of this constraint is that it increases scalability, reliability, and visibility. The disadvantage is that it decreases performance because messages need to be larger to maintain stateless communication.

Cacheable

The server responses must be cacheable. The RESTful interface should provide a mechanism for marking messages as cacheable or noncacheable. This can be implicit, explicit, or negotiated and allows the client to reissue a message if necessary.

Layered System

The client cannot assume direct access to the server. The response may be a cached response, or it may retrieve the resource directly from the server. This improves scalability because there might be software or hardware between the client and the server.

Code on Demand

This constraint defines a REST architecture as consisting of hierarchical layers that are limited to communicating with their immediate neighbors. This separation of concerns simplifies the architecture and isolates disparate and legacy components. The principle benefit you receive is an increase in scalability because new components can be easily introduced and obsolete ones retired or replaced. The drawback of this constraint is a reduction in the system’s performance resulting from the increased indirection related to the multiple layer structure.

This constraint allows a client to download and execute code from the server, which enables the server to temporarily extend the client by transferring logic. This may be in the form of a JavaScript snippet. The code on demand constraint is the only optional one.

Violating any of these constraints (except code on demand) means that the service is not strictly RESTful. A constraint violation does not mean the service is not a viable and useful implementation, however.

RICHARDSON MATURITY MODEL OF REST API

You have already read about how a truly RESTful API achieves level 3 of the Richardson Maturity Model. Now you’ll look a little deeper and examine each level on the model.

The model, developed by Leonard Richardson, attempts to classify an API according to its adherence to the constraints imposed by REST. The more compliant your implementation, the better it fares. There are four levels. The bottom is level 0, which designates the less compliant implementation, and the top is level 3, which is the most compliant and therefore the most RESTful.4

Level 0: The Swamp of POX (Plain Old XML)

This model uses HTTP as a transport protocol to invoke remote interactions. It does not use the protocol to indicate an application state; it is usually just used to tunnel requests and responses on one URI, such as /getUser, using only one HTTP method. This is a classic example of an RPC model and is more akin to SOAP and XML-RPC than REST.

Level 1: Resources

This is where the model starts to be able to distinguish between different resources. It will talk to different end points because each end point represents a different resource. It uses a URI like POST resources/123, but it still uses just one HTTP method.

Level 2: HTTP Verbs

At this level, you implement full use of the HTTP verbs and combine them with your resource nouns to provide the type of REST that has been discussed so far in this chapter. You take full advantage of the features that HTTP offers to implement your RESTful API. However, you still have not reached the level of a truly RESTful API.

Level 3: Hypermedia Controls

At this level, the model uses HATEOAS (Hypermedia As The Engine Of Application State) to direct the application state. The objective of hypermedia controls is to advise the client of what can be done next and to supply the URIs necessary to perform the next action. You will see how this works and how to implement HATEOAS later in this chapter.

DESIGNING A RESTFUL API

A well-designed RESTful API means a well-defined uniform interface. For this, a thorough understanding of the HTTP methods and response codes is important, and a complete knowledge of the data structure of your application is needed. The objective is to combine them into a simple, clean, and beautiful resource URI.

You will soon learn the elements that make up a URI.

Resource Naming

RESTful APIs are written for clients and should have meaning for the clients of those APIs. When choosing nouns to name the resources, you should be familiar with the structure of the application’s data and how your clients are likely to use them. There are no defined rules as to how you should name your resources, but there are conventions that, if followed, can help you create a set of self-descriptive resource names that others intuitively understand.

Nouns Not Verbs

You must name the resources after nouns, not verbs or actions. The purpose of the resource name is to represent the resource. The HTTP method describes the action to be performed. The next section covers the HTTP method in more detail. To represent a single user resource, you would use the noun users to represent all users and the user’s ID to identify the specific user, like so: users/123456. An example of a non-REST and badly formed URI would be users/123456/update, or it would include the action in a query string such as users/123456?action=update.

The nature of data is that it is hierarchical. So imagine that you want to represent all the posts of the user with ID 123456. You would use the noun posts to represent all posts and create the URI users/123456/posts. Earlier, it was mentioned that the representation of the resource is not the actual resource itself, but a representation of the resource, and the same resource can be represented in different ways. To represent all posts by a specified user, you can use the URI posts/users/123456. Once you have a representation of a resource, you can decide what you want to do with it by using one of the four HTTP methods. To retrieve a resource, you use the GET method, and to create a resource, you use the POST method. More on this in the next section.

Self-Descriptive

As you have seen, the nouns chosen should reflect the resource they represent. Combining these representations with identifiers makes the URI easy to interpret and intuitive to understand. If you read a URI in combination with its HTTP method and it is not immediately obvious what resource it represents, it has failed as a RESTful URI.

Plural Not Singular

Resource names should be plural because they represent collections of data. The resource name users represents a collection of users, and the resource name posts represents a collection of posts. The idea is that plural nouns represent a collection in the service, and the ID refers to one instance within that collection. It may be justifiable to use a singular noun if there is only one instance of that data type in the entire application, but this is quite uncommon.

HTTP Methods

There are eight HTTP methods defined in Hypertext Transfer Protocol 1.1; however, only four are commonly used when designing RESTful APIs. They are GET, POST, PUT, and DELETE. These methods have specified meanings and usages within the context of REST. The concept of idempotency is especially important when considering the HTTP method. The meaning of idempotency from a RESTful API point of view is that a call repeatedly made by a client to the same URI will always produce the same result. So making one request produces the same outcome, on the server, as the request made multiple times. (This assumes that a different and separate operation has not changed the resource’s state.)

Only one of the four most commonly used methods is idempotent: GET. This means that any resource URI that is executed with this method cannot effect change on the server. You cannot use it to create, update, or delete a resource. The HTTP 1.1 specification refers to this method as safe because it “should not have the significance of taking an action other than retrieval.” In the context of REST, this method is used for getting a resource’s representation from the server. It must never be used to make changes to data.

The other three methods—POST, PUT, and DELETE—are not idempotent methods and are expected to effect change on the server. You’ll learn about each method and how to use it in the context of a forum site. You’ll also learn about the HTTP response codes (http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html) that can be returned, along with the responses to the client and what they mean.

GET

You use this method to get resource representations from the service. You should never use it to update, delete, or create a resource. Calling it once should have the same effect as calling it 100 times. If the resource requested is successful, the representation of the resource is returned in the body of the HTTP response in the requested data format, which commonly is either JSON or XML. The HTTP response code returned is 200 (OK). If the resource is not found, it should return 404 (NOT FOUND), and if the resource request is badly formed, it should return 400 (BAD REQUEST). A well-formed URI that you might use in your forum application could be GET users/123456/followers, which represents all the followers of the user 123456.

POST

You use the POST method to create a new resource within the given context. For example, to create a new user, you would post to the users resource the data necessary for a new user to be created. The service takes care of creating the new resource, associating it to the context, and assigning an ID. On successful creation, the HTTP response is 201 (CREATED), and a link to the newly created resource is returned either in the Location header of the response or in the JSON payload of the response body. The resource representation may be returned in the response body. This is often preferable to avoid making an additional call to the API to retrieve a representation of the data that had been just created. This reduces the chattiness of the API.

In addition to the HTTP response codes to a GET request, a POST can return 204 (NO CONTENT) if the body of the request is empty. A well-formed URI that you might use in your forum application could be POST users, with a request body containing the new user’s details or POST users/123456/posts to create a new post for the user 123456 from the data in the request body.

PUT

The PUT method is most commonly used to update a known resource. The URI includes enough information to identify the resource, such as a context and an identifier. The request body contains the updated version of the resource, and if the update is successful, it returns the HTTP response code 200. A URI that updates a user’s information is PUT users/123456. Less commonly, you can use the PUT method to create a resource if the client creates the identifier of the resource. However, this way of creating a resource is a little confusing. Why use a PUT when a POST works just as well and is commonly known? An important point to note about updating a resource is that the entire representation of the resource is passed to the service in the HTTP body request, not just the information that has changed.

DELETE

Surprisingly, you use this method to delete a resource from a service. The URI contains the context and the identifier of the resource. To delete a user with the ID 123456, you use the URI DELETE users/123456. The response body may include a representation of the deleted resource. A successful deletion results in a 200 (OK) HTTP response code being returned; if the resource is not found, a 400 code is returned.

REST IN ACTION

You are going to design the RESTful API for a forum site using what you have learned so far.

You start by examining the data structure of the site and identifying the data domains. The two main domains are users and posts. Users can be further analyzed into followers, and posts are often organized under topics. So with these domains, start thinking about the URI you need to represent these resources.

The users noun

To create a new user, you know that you must use POST and the users context, so a URI that creates a user would look like this:

POST /users

The body of the request contains all that you need to create the new user. The response includes the URI to the representation of the user. This is a GET method request, like so: GET /users/123456. This requests details of the user with ID 123456.

If you want to update the user, you need to use the PUT method like so: PUT /users/123456.

And if you want to delete the user, you use the DELETE method, like so: DELETE /users/123456.

If you want to do a batch delete, it is acceptable to pass all the IDs of the users you want to delete in the body of a call to DELETE /users. This would be far less chatty than multiple calls to each user’s resource.

You might want to get all users in the service like so: GET /users. This call would, of course, be restricted by security so that only the users that the caller is authorized to view would be returned.

That is all for the user’s context. Now you’ll look at the follower’s. A follower is a user who follows another user because he is interested in that person’s posts.

To get all the followers for a given user, use the GET method, like so:

GET /users/123456/followers

To create a new follower of a user, you pass the ID of that follower in the body of a request to POST /users/123456/followers. You can get the details of the follower in one of two ways:

GET /users/123456/followers/456789

or

GET /users/456789

This is an example of how you can represent a resource in two different ways. To delete a follower of a given user, you can do this:

DELETE /users/123456/followers/456789

This action removes user 456789 as a follower of user 123456 but does not actually delete the user. However, the following deletes the user:

DELETE /users/456789

You have read about the followers context. Now you’ll look at the topics and posts.

The topics noun and the posts noun

You have already seen how to create a user by using the POST method. The same is true when creating a topic and a post.

To create a topic, use:

POST /topics

To create a post under a topic, use:

POST /topics/123/posts

Note that you cannot create a post by doing this:

POST /posts

because you have no context. There is not enough information for the service to create a post because you don’t know to which topic the post should be associated.

To get a topic and a post, use:

GET /topics/123

To get a specific post under a topic, use:

GET /topics/123/posts/456

or

GET /posts/456

To delete a topic or a post, use:

DELETE /topics/123

To delete a post, use:

DELETE /topics/123/posts/456

or

DELETE /posts/456

To amend a post or a topic, use can any of the following three methods:

PUT /topics/123

PUT /topics/123/posts/456

or

PUT posts/456

Now that you have the simplest URIs and contexts defined, you can start to have some fun and combine the users, topic, and post to make them more complicated.

To retrieve a representation of all topics posted by a given user, use this:

GET /users/123456/posts

To get all posts under a given topic for a given user, use this:

GET /users/123456/topics/123/posts

To get all posts by a follower of a given user of a given topic, use this:

GET /users/123456/followers/456789/topics/123/posts

You can be creative with your combinations of resource. Despite the seemingly complicated nature, you must never forget that the clients of the RESTful API use the URIs, so the URIs should be easy to understand, and nesting should be kept to a minimum. If you feel that your URI is so complicated that it should be accompanied by an explanation, you should consider refactoring it.

An example of a well-designed and thought out RESTful API has been implemented by the cloud storage company Sugarsync (https://www.sugarsync.com/developer). I recommend that you review their resource reference to see how they clearly define the folder, address, and workspace resources. Note how the HTTP methods are used to create, read, and delete resources.

IMPLEMENTING REST IN JAVA EE

This chapter has discussed at length the theory behind a well-designed RESTful API. Now that you have seen how you might style the URIs, you can jump in and see how all this looks in code.

Java EE 7 provides some helpful annotations that make the job of constructing a RESTful API straightforward. The most useful is the @Path annotation. This annotation defines the context URI and the class or method that will process requests made on that URI. Additionally, there are annotations for each HTTP method: @GET, @POST, @PUT, @DELETE, and so on. These annotations mark methods that will process requests made with the stated HTTP method.

Your application can have more than one RESTful context. To take care of this case, the @ApplicationPath annotation takes a parameter that denotes the space in which your RESTful API will exist. With just these two types of annotations, you have all you need to implement a simple RESTful API.

Now in Listing 13-1 you’ll implement the URI GET /users.

If you have this application deployed on your local machine and your application is called forum, you can test this URI by visiting http://localhost/forum/users. You should notice the text message Here we return a representation of all users displayed in the browser window.

Note in Listing 13-1 how you can annotate the class with the @Path annotation and pass it the users context. The string that you pass does not have to be preceded by a forward slash or be followed by a trailing slash. The space in which the RESTful interface will exist has been defined as the root ("/") of the application. The method that is called when a GET request is made to the URI users is annotated with the @GET annotation. In this simple example, a string is returned, but the real goal is to send back the data retrieved for the database in a JSON or XML format along with an HTTP status code. This is what occurs in Listing 13-2.

Listing 13-2 generates a JSON object from the user data that’s in the database (for brevity, a method is used to return the user data) and sends it back to the client with a 200 HTTP response code. The first thing you will notice is that the getUsers() method is now annotated with @Produces(MediaType.APPLICATION_JSON); this specifies the MIME type that this method can produce and returns to the client. The javax.json.Json and javax.json.JsonArrayBuilder classes are used to build the JSON and wrap it as a javax.ws.rs.core.Response object before returning it to the client. If all goes well, you should see the following output in the browser:

[
    {"id":123456,"firstname":"Alex","lastname":"Theedom"},
    {"id":456789,"firstname":"Murat","lastname":"Yener"}
]

So far, you have seen how to retrieve a resource representation of all users in the system, but what if you only want one user and you know the user’s identification number? Well, this is just as simple. In the URI, you pass the user’s ID number like so:

GET /users/123456

and in the REST controller class, you recuperate the ID number by referencing the REST path and using a URI variable to pass the ID to the method. You annotate the method that will consume the RESTful API call with @Path("/{id}"), and in the signature of the method, you annotate the argument to which the ID value should be passed.

    @GET
    @Path("/{id}")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getUser(@PathParam("id") String id){
        User user = this.findUser(id);
        JsonArrayBuilder jsonArrayBuilder = Json.createArrayBuilder();
        jsonArrayBuilder.add(
                        Json.createObjectBuilder()
                                        .add("id", user.getId())
                                        .add("firstname", user.getFirstname())
                                        .add("lastname", user.getLastname())
        );

        return Response.ok(jsonArrayBuilder.build()).build();
    }

    public User findUser(String id){
        return new User("123456", "Alex","Theedom");
    }

As you can see in the previous code snippet, the ID string parameter is annotated with @PathParam("id") so that the ID recuperated from the URI by the @Path("/{id}") annotation is passed into the method. It is not necessary to include the full path of the URI in the @Path annotation because the base URI is set in the @Path annotation on the class. All paths set on methods are relative to the base path set on the class.

The URI variable can be a regular expression. For example, the path annotation @Path("/{id: [0-9]*}") will match only IDs that are numbers. Any IDs that don’t match will result in a 404 HTTP response being returned to the client.

You have seen some simple URI constructions that consist of one resource noun and a URI variable. How do you deal with a more complicated URI, such as GET /users/123456/followers/456789? You do it in the same way as before, just with a slightly more complicated @Path and @PathParam.

    @GET
    @Path("/{user_id}/followers/{follower_id}")
    @Produces(MediaType.APPLICATION_JSON)
    public Response getUser(
    @PathParam("user_id") String user_id,
    @PathParam("follower_id") String follower_id)

You have looked in detail at the GET HTTP method. What about the POST, PUT, and DELETE methods? To write a method that responds to an HTTP POST request, you do almost the same as you would with GET, but you change two elements. You annotate the method with @POST instead of @GET and @Consumes in place of @Produces. Here’s a simple example:

    @POST
    @Consumes(MediaType.APPLICATION_JSON)
    @Path("/{user_id}/followers/")
    public Response createUser(@PathParam("user_id") String user_id, String body)

This example works in the same way as for the GET methods, but notice that there is no explicit mapping of the HTTP request body to a method parameter. The mapping is implicit. The content of the HTTP body is passed to the only unannotated parameter that it finds in the method signature. No more than one is allowed to avoid confusion.

The PUT and DELETE HTTP methods operate in a similar way to the POST method.

Your URI may contain query parameters. You can retrieve these from the URI by annotating a parameter in the method signature with @QueryParam("page"). This annotation retrieves the page query parameter from the URI /users?page=10.

There are many more annotations in the JAX-RS API that facilitate the design of a good RESTful API. It’s recommended that you familiarize yourself with all of them.

HATEOAS

As has already been discussed, HATEOAS is at the highest level of REST implementation in the Richardson Maturity Model and should be considered the nirvana of RESTfulness.

Imagine that a client requests a resource that represents all the posts in the system that the user has permission to view. The URI would be GET /posts, and the response, if successful, might return with the following HTTP body:

{
  "posts": [
    {
      "id": 71892,
      "title": "Best movie of 2015",
      "content": "I think the best movie of 2015 is the Golden Egg of Siam.",
      "links": [
        {
          "rel": "self",
          "href": "http://localhost:8080/rest/posts/71892",
          "method": "GET"
        },
        {
          "rel": "replies",
          "href": "http://localhost:8080/rest/posts/71892/posts",
          "method": "GET"
        },
        {
          "rel": "follower",
          "href": "http://localhost:8080/rest/posts/71892/followers",
          "method": "GET"
        },
        {
          "rel": "owner",
          "href": "http://localhost:8080/rest/posts/71892/users",
          "method": "GET"
        }
      ]
    },
    {
      "id": 71893,
      "title": "Worst movie of 2015",
      "content": "The worst movie has gotta be Just Being Me.",
      "links": [
        {
          "rel": "self",
          "href": "http://localhost:8080/rest/posts/71893",
          "method": "GET"
        },
        {
          "rel": "owner",
          "href": "http://localhost:8080/rest/posts/71893/users",
          "method": "GET"
        }
      ]
    }
  ]
}

There’s a lot going on here. The response is in JSON format and is formed of one JSON object named post that contains an array of posts:

{
  "posts": [
    {
      ... element one in the array
    },
    {
      ... element two in the array
    }
  ]
}

In the example, there are only two elements to the array representing two posts. Each post is a JSON object that follows the same format:

{
      "id": 71892,
      "title": "Best movie of 2015",
      "content": "I think the best movie of 2015 is the Golden Egg of Siam.",
}

As can be seen from the JSON snippet it contains an ID that identifies the post resource followed by the post’s title and content. This is the minimum that you would expect to see in a response to a request for a post resource regardless of the maturity of the rest interface. What makes this response special is the links element.

      "links": [
        {
          "rel": "self",
          "href": "http://localhost:8080/rest/posts/71892",
          "method": "GET"
        },
        ...
      ]

This is where HATEOAS comes to life. There are three parts to each link in the link array. The rel is the relation that the href link has to the current resource. The href is a link to more resources, and the method is the method that must be used to obtain the resource. The rel element can have any value and does not have to follow a convention, although it is customary for 'self' rel to refer to a link that represents more information about the current resource. In this example, it just refers to itself. The other links refer to other users’ responses to the post (replies or responses), the users who follow the post (followers), and the user who posted the post (owner). Any resource that relates to the principle post resource can be represented by a link in the link array.

As you can see from the example, the first post in the array has four links in its links array, whereas the second has only two. This is because the second post does not have users following it or any responses.

Providing links in this way gives the client the information it needs to navigate to further resources and allows you to easily extend and grow the API with relatively little pain.

A good example of a well-designed implementation of HATEOAS is the one implemented by Paypal
.com (https://developer.paypal.com/webapps/developer/docs/integration/direct/paypal-rest-payment-hateoas-links/). They have used HATEOAS to allow you to build an API that interacts with their payment system simply by following the links provide in the links array.

WHERE AND WHEN TO USE REST

REST is an easy and well-established approach that is not constrained by standards. Some may argue that this is a distinct disadvantage when compared to SOAP, which is an industry standard with its own well-defined protocol and implementation rules. However, its ease of implementation and use by others outweighs any difficulty created by a lack of a standard. Making a RESTful resource for consumption is as simple as providing a URI, and using the HTTP protocol cross-language communication is easy. The common language is HTTP, the language of the web, which is simple and understood by all.

Bandwidth limitation situations prove no problem for REST’s lightweight approach and are especially attractive on mobile devices. It costs little to make a request for a resource from a RESTful API. Remember that it is just an HTTP request and that the data returned can be in any appropriate format. The format does not have to be JSON or XML; it can be Atom Syndicate Format (ATOM) or some custom format. The flexibility afforded by using just a simple URI to represent a resource allows the client developer to be imaginative. You can use Asynchronous Javascript and XML (AJAX) to call one or more URIs, perhaps from different REST providers. You can combine the responses to these calls to provide rich content for the site’s visitors.

If your implementation of REST uses the HTTP protocol (which it most probably will), you receive the bonus feature of free caching. The HTTP protocol incorporates a cache as a core feature that you can exploit in your application by setting appropriate HTTP header values.

SUMMARY

Your application’s REST API should be simple and intuitive for other developers to use, and it is your responsibility as a developer to design an API that fits the requirement of your application while ensuring that the API’s users can access the resources required for the proper function of their application.

In this chapter we have touched upon the basics of a good RESTful API design. There are many more considerations that we have not even mentioned, such as security, the use of query strings, and how to provoke server side tasks.

Luckily REST is ubiquitous, and resources to help you develop a truly RESTful API are plentiful. Just search the Internet and you will not be at a loss for articles, forums, and books devoted to the topic of REST.

  EXERCISES  

  1. Search the Internet for public RESTful APIs, and write some simple code that consumes them.

  2. Implement the URI for the forum site detailed in the preceding text, and write a front end client that consumes them.

  3. Develop one journey through the site using a fully HATEOAS-style approach.

NOTES

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.133.146.237