As the world has moved into the big data era, collecting and dealing with data alone has become the main part of most of our web applications, and web services, too, as web services deal only with data, not the other parts of the user experience, look, and feel. Even though user experience is very important for all web applications, web services play a major role in dealing with data by consuming services from the client side.
In the early days of web services, Simple Object Access Protocol (SOAP) was the default choice for all backend developers who dealt with web service consumption. SOAP was mainly used in HTTP and Simple Mail Transfer Protocol (SMTP) for message transmission across the same or different platforms. When there was no JavaScript Object Notation (JSON) format available for web services, XML used to be the only available format SOAP could use for the web service consumption.
However, in the JSON era, Representational State Transfer (REST) started dominating web service based applications, as it supports multiple formats, including JSON, XML, and other formats. REST is simpler than SOAP, and the REST standards are easy to implement and consume. Also, REST is lightweight as compared to SOAP.
In this chapter, we will cover the following topics:
- REST—a basic understanding
- Reactive programming and its basics, including the benefits of Reactive programming
- Spring 5 basics with Reactive programming
- A sample RESTful web service that will be used as a base for the rest of the book
Contrary to popular belief, REST is not a protocol, but an architectural principle for managing state information. It's mainly used in web applications. REST was introduced by Roy Fielding to overcome implementation difficulties in SOAP. Roy's doctoral dissertation made for an easy way to retrieve data, regardless of the platform used. You will see all the components of RESTful web services in the following sections.
In REST principles, all resources are identified by the Uniform Resource Identifier (URI).
HTTP REST resources are represented in some media types, such as XML, JSON, and RDF. Also, RESTful resources are self-descriptive, which means enough information is given to describe how to process the request.
In another REST principle, the clients interact with servers through hypermedia, which is dynamically provided by the servers. Other than endpoints, clients don't need to know how to interact with RESTful services. This principle is referred to as Hypermedia as the Engine of Application State (HATEOAS).
By separating REST entities such as the client and server, we can reduce the complexity of REST principles, which will show clear boundaries between server and client. This decoupling will help developers concentrate on the client and server independently. Also, it will help to manage different roles for the client and server.
In REST principles, the server will not keep any state about the client session on the server side; hence, it's stateless. If two calls are made to the server from a single client, the server will not identify whether both the calls are from the same client or not. As far as the server knows, every request is independent and new. Based on the URL, HTTP headers, and request body, including the parameters, the operation might be changed on the server side.
With RESTful web services, a client can cache any response coming from the server. The server can mention how, and for how long, it can cache the responses. With the caching option, a client can use the responses instead of contacting the server again. Also, caching will improve scalability and performance by avoiding client-server interactions all the time.
Note
This principle has significant advantages for scalability. Caching techniques will be discussed in Chapter 8, Performance.
Since REST typically leverages HTTP, it inherits all the caching properties that HTTP offers.
By providing the layered system, a server can hide its identity. By doing this, clients won't know which server they are dealing with. This policy gives more security control by providing intermediate servers and supports the load-balancing feature, too. Also, intermediate servers can improve scalability and performance through load-balancing and shared caches.
Code on demand (COD) is considered an optional principle. Servers can extend the functionality of clients by transferring executable code. For example, JavaScript can be provided to web-based clients to customize the functionality. As code on demand reduces the visibility of the client side, this constraint is optional. Also not all APIs need this feature.
In web applications, REST is typically used over HTTP. REST doesn't need to be tied to any specific protocol. In HTTP REST, we mainly use the GET
, POST
, PUT
, and DELETE
methods to change the state of the resources we access. Other HTTP methods, such as OPTIONS
, HEAD
, CONNECT
, and TRACE
, can be used for more advanced operations, for example, for caching and debugging purposes. Most servers have disabled advanced methods for security and simplicity reasons; however, you can enable them by adjusting the server configuration files. As JSON is used as a primary media type for major applications, we also use only the JSON media type for our web service calls.
Let's see a small comparison between Imperative programming and Reactive programming: x = y + z.
In the preceding expression, assume y = 10 and z = 15. In this case, the x value would be 25. The value of x would be assigned at the time of the expression x = y + z. The value of x will never change after this expression.
This is perfectly alright in the traditional programming world. However, we might need a scenario where we should be able to follow up x when we change the value of y or z.
Our new scenario based values are:
- When y = 20 and z = 15, then x = 35
- When y = 20 and z = 25, then x = 45
The preceding scenario is not possible in Imperative programming, which we regularly use in our daily programming. But in some cases, we might need the value of x to be updated, corresponding to the change in y or z. Reactive programming is the perfect solution for this scenario. In Reactive programming, the value of x would automatically be updated, corresponding to the change in y or z.
Spreadsheet reference cells are the best example of Reactive programming. If a cell value changes, the referred cell value will be updated automatically. Another example can be found in a Model-View-Controller architecture, Reactive programming can automatically update the View, which is attached to the Model.
Reactive programming follows the Observer pattern to manipulate and transform the stream of data where the Publisher (observable) emits the items based on the Subscriber's need. As the Publisher emits the item, the Subscriber consumes those emitted items from the Publisher. Unlike the iterator pulling the items, here, the Publisher is pushing the items to the Subscriber.
As Reactive is a part of non-blocking architecture, it will be useful when we scale the application. Also, in non-blocking architecture, everything is considered as an event stream.
We will discuss more about Reactive in Java and Spring later in this chapter.
Reactive Streams are all about processing an asynchronous stream of data items, where applications react to data items as they receive them. This model is more memory-efficient, as it doesn't rely on any in-memory data.
Reactive Streams have four main components:
- Publisher.
- Subscriber.
- Subscription.
- Processor.
The Publisher publishes a stream of data, to which the Subscriber is asynchronously subscribed. The Processor transforms the data stream without the need for changing the Publisher or the Subscriber. The Processor (or multiple Processors) sits between the Publisher and the Subscriber to transform one stream of data to another.
The Reactive Streams approach is supported by engineers at Netflix, Pivotal, Twitter, Oracle, and TypeSafe. Especially, TypeSafe contributed more to Reactive Streams. Even Netflix engineers say, in their own words:
“Reactive programming with RxJava has enabled Netflix developers to leverage server-side concurrency without the typical thread-safety and synchronization concerns.”
The following are the benefits of Reactive programming:
- Focuses on business logic
- Stream processing causes memory efficiency
- Overcomes low-level threading, synchronization, and concurrency issues
Reactive principles are used in real-time cases such as live database queries, big data, real-time analytics, HTTP/2, and so on.
RxJava was introduced by Netflix engineers to support the Reactive model in Java 8, with the bridge to Reactive Streams. However, Java started supporting the Reactive model with Java 9, and Reactive Streams have been incorporated into the JDK as java.util.concurrent.Flow
in Java 9.
Also, Pivotal introduced the Reactor framework, which is built directly on Reactive Streams, avoiding the external bridge to Reactive Streams. A Reactor is considered as a 4th generation library.
Finally, Spring Framework 5.0 added Reactive features built into it, including the tools for HTTP servers and clients. Spring users find annotations and controllers handy when they deal with HTTP requests, especially dispatching Reactive requests and back pressure concerns to the framework.
The Reactive model seems to be efficient in resource utilization, as it can process higher loads with fewer threads. However, the Reactive model may not be the right solution for all problems. In some cases, Reactor may make things worse if we use it in the wrong section.
As we assume that our readers are familiar with Spring Framework, we will directly focus on the example service that we are going to build.
In this book, we are going to build a Ticket Management System. To give a clear picture of the Ticket Management System and how it's going to be used, we will come up with a scenario.
Let's assume that we have a banking web application used by our customers, Peter and Kevin, and we have Sammy, our admin, and Chloe, the customer service representative (CSR), to help in case of any banking application issues.
If Kevin/Peter is facing a problem in the web application, they can create a ticket in our Ticket Management System. This ticket will be handled by the admin and sent to CSR, who handles the ticket.
The CSR gets more information from the user and forwards the information to the technical team. Once the CSR resolves the issue, they can close the issue.
In our Ticket Management System we will be using the following components:
Ticket |
|
User |
|
In this Ticket Management System, we will focus on:
- Creating a ticket by the user.
- Updating the ticket by the user.
- Updating the ticket status by the admin.
- Updating the ticket status by the CSR.
- Deleting the ticket by the user and admin.
In the initial chapters we will discuss User management to keep the business logic simple when we deal with topics such as AOP, Spring Security, and WebFlux. However, we will talk about the Ticket Management System in Chapter 13, Ticket Management - Advanced CRUD and implement all the business requirements that we mentioned earlier. In Chapter 13, Ticket Management - Advanced CRUD you will use all the advanced techniques employed in other chapters to finish our business requirements.
So far, we have gone through the basics of REST and Reactive programming and the necessity for Reactive Streams. We have gone through Spring 5 with Reactor support. Also, we have defined the business sample and architecture that will be used in the rest of the book.
In the next chapter, we will talk about simple project creation with Maven and the simple REST API. Also, we will discuss Maven file structure and dependencies, including samples.