Book Image

RESTful Java Web Services - Third Edition

By : Balachandar Bogunuva Mohanram, Jobinesh Purushothaman
Book Image

RESTful Java Web Services - Third Edition

By: Balachandar Bogunuva Mohanram, Jobinesh Purushothaman

Overview of this book

Representational State Transfer (REST) is a simple yet powerful software architecture style to create lightweight and scalable web services. The RESTful web services use HTTP as the transport protocol and can use any message formats, including XML, JSON(widely used), CSV, and many more, which makes it easily inter-operable across different languages and platforms. This successful book is currently in its 3rd edition and has been used by thousands of developers. It serves as an excellent guide for developing RESTful web services in Java. This book attempts to familiarize the reader with the concepts of REST. It is a pragmatic guide for designing and developing web services using Java APIs for real-life use cases following best practices and for learning to secure REST APIs using OAuth and JWT. Finally, you will learn the role of RESTful web services for future technological advances, be it cloud, IoT or social media. By the end of this book, you will be able to efficiently build robust, scalable, and secure RESTful web services using Java APIs.
Table of Contents (11 chapters)

The core architectural elements of a RESTful system

Having learned the basics of a RESTful system, you are now ready to meet more exciting concepts around REST. In this section, you will learn the core architectural elements that make a system RESTful.

Analogous to any software architecture, the REST architecture is also defined by a configuration of key architectural elements (components, connectors, and data) with a set of constraints, as shown in the following diagram:

Data elements

The central feature that distinguishes the REST architectural style from other network-based styles is its emphasis on a uniform interface between components, which abstracts the information being transmitted. A uniform interface is fundamental to the architecture of any RESTful system. In plain words, this term refers to a generic interface to manage all interactions between a client and server in a unified way. All resources (or business data) involved in the client-server interactions are dealt with a fixed set of operations. The following are the core elements that form a uniform interface for a RESTful system:

  • Resources and their identifiers
  • The representation of resources
  • Generic interaction semantics for the REST resources
  • Self-descriptive messages
  • Hypermedia as the engine of an application state

Let's look at these items in detail in the following section.

Resources

A RESTful resource is anything that is addressable over the web. By addressable, we mean resources that can be accessed and transferred between clients and servers. Subsequently, a resource is a logical, temporal mapping to a concept in the problem domain for which we are implementing a solution.

Here are some examples of REST resources:

  • A news story
  • The temperature in NY at 4:00 p.m. EST
  • A tax return stored in the IRS database
  • A list of code revision history in a repository such as SVN or CVS
  • A student in a classroom in a school
  • A search result for a particular item in a web index, such as Google

Even though a resource's mapping is unique, different requests for a resource can return the same underlying binary representation stored in the server. For example, let's say we have a resource within the context of a publishing system. Then, a request for the latest revision published and the request for revision number 12 will at some point in time return the same representation of the resource. In this example, the last revision is version 12. However, when the latest revision published is increased to version 13, a request to the latest revision will return version 13, and a request for the revision of version 12 will continue returning version 12. This implies that in a RESTful architecture, each resource can be accessed directly and independently, and sometimes, different requests may point to the same resource.

As we are using HTTP to communicate, we can transfer a variety of data types between clients and servers, as long as the data type used is supported by HTTP. For example, if we request a text file from CNN, our browser receives a text file. If we request a Flash movie from YouTube, our browser receives a Flash movie. The data is streamed in both cases over TCP/IP and the browser knows how to interpret the binary streams because of the Content-Type header present in the HTTP response header. Following this principle, in a RESTful system, the representation of a resource in the response body depends on the desired internet media type, which is specified within the request header sent by the client.

URI

A URI is a string of characters used to identify a resource over the web. In simple words, the URI in a RESTful web service is a hyperlink to a resource, and it is the only means for clients and servers to exchange representations.

The client uses a URI to locate the resources over web, sends a request to the server, and reads the response. In a RESTful system, the URI is not meant to change over time as it may break the contract between the client and server. More importantly, even if the underlying infrastructure or hardware changes (for example, swapping the database servers) for a server hosting the REST APIs, the URIs for the resources are expected to remain the same as long as the web service is up and running.

The representation of resources

The representation of resources is what is sent back and forth between clients and servers in a RESTful system. A representation is a temporal state of the actual data located in a storage device at the time of request. In general terms, it is a binary stream, together with its metadata, which describes how the stream is to be consumed by the client. The metadata can also contain extra information about the resource, for example, validation, encryption information, or extra code to be executed at runtime.

Throughout the life of a web service, there may be a variety of clients requesting resources. Different clients can consume different representations of the same resource. Therefore, a representation can take various forms, such as an image, a text file, an XML, or a JSON format. However, all clients will use the same URI with appropriate Accept header values for accessing the same resource in different representations.

For the human-generated requests through a web browser, a representation is typically in the form of an HTML page. For automated requests from other web services, readability is not as important, and a more efficient representation, such as JSON or XML, can be used.

Generic interaction semantics for REST resources

In the previous sections, we introduced the concepts of resources and representations. We learned that resources are mappings of the actual entity states that are exchanged between clients and servers. Further, we discussed that representations are negotiated between clients and servers through the communication protocol (HTTP) at runtime. In this section, you will learn about the generics of interaction semantics and self-descriptive messages followed for the client-server communication in a RESTful system.

Developing RESTful web services is similar to what we have been doing up to this point with our web applications. In a RESTful web service, resources are exchanged between the client and the server, which represent the business entities or data. HTTP specifies methods or actions for the resources. The most commonly used HTTP methods or actions are POST, GET, PUT, and DELETE. This clearly simplifies the REST API design and makes it more readable. On the other hand, in traditional application development, we can have countless actions with no naming or implementation standards. This may call for more development effort for both the client and the server and make the APIs less readable.

In a RESTful system, we can easily map our CRUD actions on the resources to the appropriate HTTP methods such as POST, GET, PUT, and DELETE. This is shown in the following table:

Data action

HTTP equivalent

CREATE

POST or PUT

READ

GET

UPDATE

PUT or PATCH

DELETE

DELETE

In fact, the preceding list of HTTP methods is incomplete. There are some more HTTP methods available, but they are less frequently used in the context of RESTful implementations. Of these less frequent methods, OPTIONS and HEAD are used more often than others. So, let's glance at these two method types:

  • OPTIONS: This method is used by the client to determine the options or actions associated with the target resource, without causing any action on the resource or retrieval of the resource
  • HEAD: This method can be used for retrieving information about the entity without having the entity itself in the response

In their simplest form, RESTful web services are networked applications that manipulate the state of resources. In this context, resource manipulation means resource creation, retrieval, updation, and deletion. However, RESTful web services are not limited to just these four basic data manipulation concepts. They can even be used for executing business logic on the server but remembering that every result must be a resource representation of the domain at hand.

A uniform interface brings all the aforementioned abstractions into focus. Consequently, putting together all these concepts, we can describe RESTful development with one short sentence--we use URIs to connect clients and servers in order to exchange resources in the form of representations.

Let's now look at the four HTTP request types in detail and see how each of them is used to exchange representations to modify the state of resources.

The HTTP GET method

The GET method is used to retrieve resources. Before digging into the actual mechanics of the HTTP GET request, we first need to determine what a resource is in the context of our web service and what type of representation we are exchanging.

For the rest of this section, we will use the example of a RESTful web service handling the department details for an organization. For this service, the JSON representation of a department looks as follows:

{"departmentId":10,"departmentName":"IT","manager":"John Chen"} 

The JSON representation of the list of departments looks as follows:

[{"departmentId":10,"departmentName":"IT","manager":"John Chen"}, 
{"departmentId":20,"departmentName":"Marketing","manager":"Ameya
J"},
{"departmentId":30,"departmentName":"HR","manager":"Pat Fay"}]

With our representations defined, we can now assume URIs of the form http://www.packtpub.com/resources/departments to access a list of departments, and http://www.packtpub.com/resources/departments/{name} to access a specific department with a name (unique identifier).

To keep this example simple and easy to follow, we treat the department name as a unique identifier here. Note that in real life, you can use a server-generated identifier value, which does not repeat across entities, to uniquely identify a resource instance.

We can now begin making requests to our web service. For instance, if we wanted a record for the IT department, we make a request to the following URI: http://www.packtpub.com/resources/departments/IT.

A representation of the IT department at the time of the request may look like the following code snippet:

{"departmentId":10,"departmentName":"IT","manager":"John Chen"} 

Let's have a look at the request details. A request to retrieve the details of the IT department uses the GET method with the following URI: http://www.packtpub.com/resources/departments/IT

Let's see what happens when a client requests for the IT department with the aforementioned URI. Here is the sequence diagram for the GET request:

What is happening here?

  1. A Java client makes an HTTP request with the GET method type and IT as the identifier for the department.
  2. The client sets the representation type that it can handle through the Accept request header field. This request message is self-descriptive:
    • It uses a standard method (the GET method in this example) with known semantics for retrieving the content
    • The content type is a set to a well-known media type (text/plain)
    • This request also declares the acceptable response format
  1. The web server receives and interprets the GET request to be a retrieve action. At this point, the web server passes control to the underlying RESTful framework to handle the request. Note that RESTful frameworks do not automatically retrieve resources, as that is not their job. The job of a framework is to ease the implementation of the REST constraints. Business logic and storage implementation is the role of the domain-specific Java code.
  2. The server-side program looks for the IT resource. Finding the resource could mean looking for it in some data store such as a database, a filesystem, or even a call to a different web service.
  3. Once the program finds the IT department details, it converts the binary data of the resource to the client's requested representation. In this example, we use the JSON representation for the resource.
  4. With the representation converted to JSON, the server sends back an HTTP response with a numeric code of 200 together with the JSON representation as the payload. Note that if there are any errors, the HTTP server reports back the proper numeric code, but it is up to the client to correctly deal with the failure. Similar to the request message, the response is also self-descriptive.

All the messages between a client and server are standard HTTP calls. For every retrieve action, we send a GET request, and we get an HTTP response back, with the payload of the response being the representation of the resource or, if there is a failure, a corresponding HTTP error code (for example, 404 if a resource is not found or 500 if there is a problem with the Java code in the form of an exception).

Getting a representation for all the departments works in the same way as getting the representation for a single department, although we now use the URI as http://www.packtpub.com/resources/departments and the result is the JSON representation, which looks as follows:

[{"departmentId":10,"departmentName":"IT","manager":"John Chen"}, 
{"departmentId":20,"departmentName":"Marketing","manager":"Ameya
J"},
{"departmentId":30,"departmentName":"HR","manager":"Pat Fay"}]
The HTTP GET method should only be used to retrieve representations, not for performing any update on the resource. A GET request must be safe and idempotent. For more information, refer to http://www.w3.org/DesignIssues/Axioms.

For a request to be safe, it means that multiple requests to the same resource do not change the state of the data in the server. Assume that we have a representation, R, and requests happen at time t. Then, a request at time t1 for the resource R returns R1; subsequently, a request at time t2 for the resource R returns R2, provided that no further update actions have been taken between t1 and t2. Then, R1 = R2 = R.

For a request to be idempotent, multiple calls to the same action should not change the state of the resource. For example, multiple calls to create the resource R at times t1, t2, and t3 means that R will exist only as R and the calls at times t2 and t3 are ignored.

The HTTP POST method

The POST method is used to create resources. As we are creating a department, we use the HTTP POST method. Again, the URI to create a new department in our example is http://www.packtpub.com/resources/departments. The method type for the request is set by the client.

Assume that the Sales department does not exist in our list, and we want to add it to the list. The Sales data representation looks like the following:

{"departmentName":"Sales","manager":"Tony Greig"} 

Now, the sequence diagram of our POST request looks like the following:

The series of steps for the POST request is as follows:

  1. A Java client makes a request to the http://www.packtpub.com/resources/departments URI with the HTTP method set to POST.
  2. The POST request carries the payload along with it in the form of a JSON representation of the Sales department.
  3. The server receives the request and lets the REST framework handle it; our code within the framework executes the proper commands to store the representation, irrespective of which data persistence mechanism is used.
  4. Once the new resource is stored, a response code, 2xx (representing successful operation), is sent back. In this example, the server sends 201 Created, which implies that the server has fulfilled the request by creating a new resource. The newly created resource is accessible by traversing the URI given by a Location header field. If it fails, then the server sends the appropriate error code.

The HTTP PUT method

The PUT method is used to update resources. To update a resource, we first need its representation in the client. Then, at the client level, we update the resource with the new value(s) that we want. Finally, we update the resource by using a PUT request together with the representation as its payload.

In this example, let's add a manager to the Sales department, which we created in the previous example.

Our original representation of the Sales department is as follows:

{"departmentId":40,"departmentName":"Sales","manager":"Tony 
Greig" }

Let's update the manager for the Sales department; our representation is as follows:

{"departmentId":40,"departmentName":"Sales","manager":"Ki Gee"} 

We are now ready to connect to our web service to update the Sales department by sending the PUT request to http://www.packtpub.com/resources/departments/Sales. The sequence diagram of our PUT request is as follows:

The series of steps for the PUT request is as follows:

  1. A Java client makes a PUT request to http://www.packtpub.com/resources/departments/Sales with the JSON payload representing the modified department details.
  2. The server receives the request and lets the REST framework handle it. At this point, we let our code execute the proper commands to update the representation of the Sales department. Once completed, a response is sent back. The 204 No Content response code indicates that the server has fulfilled the request but does not return the entity body.

The HTTP DELETE method

The DELETE method is used to delete the resource. In this example, we will delete a resource by making use of the same URI that we used in the other three cases.

Assume that we want to delete the Sales department from the data storage. We send a DELETE request to our service with the following URI: http://www.packtpub.com/resources/departments/Sales

The sequence diagram for our DELETE request is shown in the following diagram:

The series of steps for the DELETE request is as follows:

  1. A Java client makes a DELETE request to http://www.packtpub.com/resources/departments/Sales.
  2. The server receives the request and lets the REST framework handle it. At this point, the server code executes the proper commands to delete the representation of the Sales department.
  3. Once completed, a response is sent back.

With this, we have covered all the major actions that can be carried out on resources in a RESTful web service. To keep things simple during our discussion, we did not talk about the actual implementation of the CREATE, READ, UPDATE, and DELETE operations on the resource. In all three examples, we presumed that we have a well-behaved web service that adheres to the RESTful guidelines, and the client and server communicate over HTTP. We use the communication protocol to send action requests, and our resource representations are sent back and forth through unchanging URIs. We will cover more detailed end-to-end examples later in this book.

A point to note about our sequence diagrams is that we are assuming that all the underlying technologies are Java technologies (servers and clients). However, these are just components in the whole architecture and the explanations apply to any technology stack.

Hypermedia as the Engine of Application State

Hypermedia as the Engine of Application State (HATEOAS) is an important principle of the REST application architecture. The principle is that the model of application changes from one state to another by traversing the hyperlinks present in the current set of resource representations (model). Let's learn this principle in detail.

In a RESTful system, there is no fixed interface between the client and the server, as you may see in a conventional client-server communication model such as Common Object Request Broker Architecture (CORBA) and Java Remote Method Invocation (Java RMI). With REST, the client just needs to know how to deal with the hypermedia links present in the response body; next, the call to retrieve the appropriate resource representation is made by using these dynamic media links. This concept makes the client-server interaction very dynamic and keeps it different from the other network application architectures.

Here is an example illustrating the HATEOAS principle. In this example, the http://www.packtpub.com/resources/departments/IT URI returns the following response to the client:

{"departmentId":10, 
"departmentName":"IT",
"manager":"John Chen,
"links": [ {
"rel": "employees",
"href": "http://packtpub.com/resources/departments/IT/employees"
} ]"}

This is the current state of the system. Now, to get the employees belonging to the department, the client traverses the hyperlink present in the response body, namely http://www.packtpub.com/resources/departments/IT/employees. This URI returns the following employee list. The application state now changes into the following form (as represented by the response content):

[{"employeeId":100, 
"firstName":"Steven",
"lastName":"King",
"links": [ {
"rel": "self",
"href": "http://www.packtpub.com/resources/employees/100"
}]
},
{"employeeId":101,
"firstName":"Neena",
"lastName":"Kochhar",
"links": [ {
"rel": "self",
"href": "http://www.packtpub.com/resources/employees/101"
}]
}]

In this example, the application state changes from one state to another when the client traverses the hypermedia link. Hence, we refer to this implementation principle as HATEOAS.

Connectors

Connectors provide decoupling between components by encapsulating the underlying implementation of resources and communication mechanisms using various connector types, as described in the following table:

Connector type

Function

Examples

Client

Initiates the request and accepts the response

Client-side web APIs (libwww, libwww-perl)

Server

Listens for connections and responds to requests

Web server APIs (Apache API, NSAPI)

Cache

Used for storing cacheable responses both at the client and server side to optimize interaction latency

Web caching solutions (Akamai, Cloudflare, Microsoft Azure CDN)

Resolver

Resolves web address to the corresponding network address

BIND, Microsoft DNS, AnswerX

Tunnel

Relays communication across a connection boundary such as firewall, gateways, or proxies.

SOCKS, HTTP Tunnel

Components

Software components required for REST are categorized by their roles as follows:

Component role

Function

Examples

Origin server

It acts as the container or definitive source for the representation of resources being requested; it must be the ultimate recipient of any requests. It uses a server connector to receive and respond to requests.

Web servers (Apache Tomcat, Microsoft IIS)

User agent

This is the user interface for the end user. It uses the client connector to initiate the request and get the response.

Web browsers (Internet Explorer, Chrome, Lynx)

Proxy

This acts as an intermediary for requests from clients seeking resources.

CGI Proxy, CERN Proxy

Gateway

This involves reverse proxies providing encapsulation of services such as security (encryption), performance enhancement (load balancing), or data translation (compression).

Squid, NGINX