Message Oriented Communication and Resource Oriented Communication
Message-oriented communication is a way of communicating between processes. Messages, which correspond to events, are the basic units of data delivered. ... In synchronous communication, the sender blocks waiting for the receiver to engage in the exchange.
A resource-oriented architecture (ROA) is the structural design supporting the internetworking of resources. A resource, in this context, is any entity that can be identified and assigned a uniform resource identifier (URI).
Resource based nature of the REST style
“The key abstraction of information in REST is a resource. Any information that can be named can be a resource: a document or image, a temporal service (e.g. "today's weather in Los Angeles"), a collection of other resources, a non-virtual object (e.g. a person), and so on. In other words, any concept that might be the target of an author's hypertext reference must fit within the definition of a resource. A resource is a conceptual mapping to a set of entities, not the entity that corresponds to the mapping at any particular point in time.” - Roy Fielding’s dissertation.
Resources form the nucleus of any REST API design. Resource identifiers (URI), Resource representations, API operations (using various HTTP methods), etc. are all built around the concept of Resources. It is very important to select the right resources and model the resources at the right granularity while designing the REST API so that the API consumers get the desired functionality from the APIs, the APIs behave correctly and the APIs are maintainable.
A resource can be a singleton or a collection. For example, “customers” is a collection resource and “customer” is a singleton resource (in a banking domain). We can identify “customers” collection resource using the URN “/customers”. We can identify a single “customer” resource using the URN “/customers/{customerId}”.
A resource may “contain” sub-collection resources also. For example, sub-collection resource “accounts” of a particular “customer” can be identified using the URN “/customers/{customerId}/accounts” (in a banking domain). Similarly, a singleton resource “account” inside the sub-collection resource “accounts” can be identified as follows: “customers/{customerId}/accounts/{accountId}”.
The starting point in selection of resources is to analyze your business domain and extract the nouns that are relevant to your business needs. More importantly, focus should be given to the needs of API consumers and how to make the API relevant and useful from the perspective of API consumer interactions. Once the nouns (resources) have been identified, then the interactions with the API can be modeled as HTTP verbs against these nouns. When they don't map nicely, we could approximate. For example, we can easily use the “nouns in the domain” approach and identify low level resources such as Post, Tag, Comment, etc. in a blogging domain. Similarly, we can identify the nouns Customer, Address, Account, Teller, etc. as resources in a banking domain.
If we take “Account” noun example, “open” (open an account), “close” (close an account), “deposit” (deposit money to an account), “withdraw” (withdraw money from an account), etc. are the verbs. These verbs can be nicely mapped to HTTP verbs. For example, API consumer can “open” an account by creating an instance of “Account” resource using HTTP POST method. Similarly, API consumer can “close” an account by using HTTP DELETE method. API consumer can “withdraw” or “deposit” money using HTTP “PUT” / “PATCH” / “POST” methods. This tutorial explains the basic resource selection and naming very well.
However, this simplistic approach may be valid at an abstract level, but breaks down once you hit more complicated domains in practice. Eventually you run into concepts which are not covered by the usual / obvious nouns. The following sections explore the art of resource modeling and the importance of modeling resources with right granularity.
Meaning of “representations” in REST style
In REST-speak, a client and server exchange representations of a resource, which reflect its current state or its desired state. REST, or Representational state transfer, is a way for two machines to transfer the state of a resource via representations.
Constraints of REST
REST defines 6 architectural constraints which make any web service – a true RESTful API.
Uniform interface
As the constraint name itself applies, you MUST decide APIs interface for resources inside the system which are exposed to API consumers and follow religiously. A resource in the system should have only one logical URI and that should provide a way to fetch related or additional data. It’s always better to synonymise a resource with a web page.
Any single resource should not be too large and contain each and everything in its representation. Whenever relevant, a resource should contain links (HATEOAS) pointing to relative URIs to fetch related information.
Also, the resource representations across system should follow certain guidelines such as naming conventions, link formats or data format (xml or/and json).
All resources should be accessible through a common approach such as HTTP GET and similarly modified using a consistent approach.
Once a developer becomes familiar with one of your API, he should be able to follow the similar approach for other APIs.
Client–server
This essentially means that client application and server application MUST be able to evolve separately without any dependency on each other. A client should know only resource URIs and that’s all. Today, this is normal practice in web development so nothing fancy is required from your side. Keep it simple.
Servers and clients may also be replaced and developed independently, as long as the interface between them is not altered.
Stateless
Roy fielding got inspiration from HTTP, so it reflects in this constraint. Make all client-server interaction stateless. Server will not store anything about latest HTTP request client made. It will treat each and every request as new. No session, no history.
If client application needs to be a stateful application for the end user, where user logs in once and do other authorized operations thereafter, then each request from the client should contain all the information necessary to service the request – including authentication and authorization details.
No client context shall be stored on the server between requests. The client is responsible for managing the state of the application.
Cacheable
In today’s world, caching of data and responses is of utmost important wherever they are applicable/possible. The webpage you are reading here is also a cached version of the HTML page. Caching brings performance improvement for client side, and better scope for scalability for a server because the load has reduced.
In REST, caching shall be applied to resources when applicable and then these resources MUST declare themselves cacheable. Caching can be implemented on the server or client side.
Well-managed caching partially or completely eliminates some client-server interactions, further improving scalability and performance.
Layered system
REST allows you to use a layered system architecture where you deploy the APIs on server A, and store data on server B and authenticate requests in Server C, for example. A client cannot ordinarily tell whether it is connected directly to the end server, or to an intermediary along the way.
Code on demand (optional)
Well, this constraint is optional. Most of the time you will be sending the static representations of resources in form of XML or JSON. But when you need to, you are free to
return executable code
to support a part of your application e.g. clients may call your API to get a UI widget rendering code. It is permitted.
All above constraints help you build a truly RESTful API and you should follow them. Still, at times you may find yourself violating one or two constraints. Do not worry, you are still making a RESTful API – but not “truly RESTful”.
Examples of different types of implementations for the elements of REST style
Connectors
Connectors represent the activities involved in accessing resources and transferring representations. Roles provide an interface for components to implement. REST encapsulates different activities of accessing and transferring representations into different connector types. The table below summarizes the connector types:
Connector Type | Description | Example |
Client | Sending requests, receiving responses. | HTTP library |
Server | Listening for requests, sending responses. | Web Server API |
Cache | Can be located at the client or server connector to save cacheable responses, can also be shared between several clients | Browser cache |
Resolver | Transforms resource identifiers into network addresses. | bind (DNS lookup library) |
Tunnel | Relays requests, any component can switch from active behavior to a tunnel behavior. | SOCKS, SSL after HTTP CONNECT |
Components
In REST, the various software that interacts with one another are called components. They are categorized by roles summarized in the table below:
Component Role | Description | Example |
Origin Server | Uses a server connector to receive the request, and is the definitive source for representations of its resources. Each server provides a generic interface to its services as a resource hierarchy. | Apache httpd, Microsoft IIS |
User Agent | Uses a client connector to initiate a request and becomes the ultimate recipient of the response. | Browser like Netscape Navigator etc |
Gateway | Act as both, client and server in order to forward - with possible translation - requests and responses. | Squid, CGI, Reverse Proxy |
Proxy | CERN Proxy, Netscape Proxy, Gauntlet |
Data Elements
The key aspect of REST is the state of the data elements, its components communicate by transferring representations of the current or desired state of data elements. REST identifies six data elements: a resource, resource identifier, resource metadata, representation, representation metadata, and control data, shown in the table below:
Data Element | Description | Example |
Resource | Any information that can be named is a resource. A resource is a conceptual mapping to a set of entities not the entity itself. Such a mapping can change over time. In general, a RESTful resource is anything that is addressable over the Web. | Title of a movie from IMDb, A Flash movie from YouTube, Images from Flickr etc |
Resource Identifier | Every resource must have a name that uniquely identifies it. Under HTTP these are called URIs. Uniform Resource Identifier (URI) in a RESTful system is a hyperlink to a resource. It is the only means for clients and servers to exchange representations of resources.The relationship between URIs and resources is many to one. A resource can have multiple URIs which provide different information about the location of a resource. | Standardized format of URI:scheme://host:port/path?queryString#fragmente.g:http://some.domain.com/orderinfo?id=123 |
Resource metadata | This describes the resource. A metadata provides additional information such as location information, alternate resource identifiers for different formats or entity tag information about the resource itself. | Source link, vary |
Representation | It is something that is sent back and forth between clients and servers. So, we never send or receive resources, only their representations. A representation captures the current or intended state of a resource. A particular resource may have multiple representations | Sequence of bytes, HTML document, archive document, image document |
Representation metadata | This describes the representation. | Headers (media-type) |
Control data | This defines the purpose of a message between components, such as the action being requested. | If-Modified-Since, If-Match |
How to define the API of RESTful web services using RESTful URLs
A RESTful API is an application program interface (API) that uses HTTP requests to GET, PUT, POST and DELETE data.
A RESTful API -- also referred to as a RESTful web service -- is based on representational state transfer (REST) technology, an architectural style and approach to communications often used in web services development.
REST technology is generally preferred to the more robust Simple Object Access Protocol (SOAP) technology because REST leverages less bandwidth, making it more suitable for internet usage. An API for a website is code that allows two software programs to communicate with each another . The API spells out the proper way for a developer to write a program requesting services from an operating system or other application.
The REST used by browsers can be thought of as the language of the internet. With cloud use on the rise, APIs are emerging to expose web services. REST is a logical choice for building APIs that allow users to connect and interact with cloud services. RESTful APIs are used by such sites as Amazon, Google, LinkedIn and Twitter.
How RESTful APIs work
A RESTful API breaks down a transaction to create a series of small modules. Each module addresses a particular underlying part of the transaction. This modularity provides developers with a lot of flexibility, but it can be challenging for developers to design from scratch. Currently, the models provided by Amazon Simple Storage Service, Cloud Data Management Interface and OpenStack Swift are the most popular.
A RESTful API explicitly takes advantage of HTTP methodologies defined by the RFC 2616 protocol. They use GET to retrieve a resource; PUT to change the state of or update a resource, which can be an object, file or block; POST to create that resource ; and DELETE to remove it.
With REST, networked components are a resource you request access to -- a black boxwhose implementation details are unclear. The presumption is that all calls are stateless; nothing can be retained by the RESTful service between executions.
Because the calls are stateless, REST is useful in cloud applications. Stateless components can be freely redeployed if something fails, and they can scale to accommodate loadchanges. This is because any request can be directed to any instance of a component; there can be nothing saved that has to be remembered by the next transaction. That makes REST preferred for web use, but the RESTful model is also helpful in cloud services because binding to a service through an API is a matter of controlling how the URL is decoded.
Pros and cons of using MVC for RESTful web service development
Here are some of the features that Web API provides:
- Strong Support for URL Routing to produce clean URLs using familiar MVC style routing semantics
- Content Negotiation based on Accept headers for request and response serialization
- Support for a host of supported output formats including JSON, XML, ATOM
- Strong default support for REST semantics but they are optional
- Easily extensible Formatter support to add new input/output types
- Deep support for more advanced HTTP features via HttpResponseMessage and HttpRequestMessage
classes and strongly typed Enums to describe many HTTP operations - Convention based design that drives you into doing the right thing for HTTP Services
- Very extensible, based on MVC like extensibility model of Formatters and Filters
- Self-hostable in non-Web applications
- Testable using testing concepts similar to MVC
Some Issues about Web API
Web API is similar to MVC but not the Same
Although Web API looks a lot like MVC it’s not the same and some common functionality of MVC behaves differently in Web API. For example, the way single POST variables are handled is different than MVC and doesn’t lend itself particularly well to some AJAX scenarios with POST data.
Code Duplication
If you build an MVC application that also exposes a Web API it’s quite likely that you end up duplicating a bunch of code and – potentially – infrastructure. You may have to create authentication logic both for an HTML application and for the Web API which might need something different altogether. More often than not though the same logic is used, and there’s no easy way to share. If you implement an MVC ActionFilter and you want that same functionality in your Web API you’ll end up creating the filter twice.
JAX-RS API
A RESTful API can be implemented in Java in a number of ways: you can use Spring, JAX-RS, or you might just write your own bare servlets if you’re good and brave enough. All you need is the ability to expose HTTP methods – the rest is all about how you organize them and how you guide the client when making calls to your API.
As you can make out from the title, this article will cover JAX-RS. But what does “just an API” mean? It means that the focus here is on clarifying the confusion between JAX-RS and its implementations and on offering an example of what a proper JAX-RS webapp looks like.
2. Inclusion in Java EE
JAX-RS is nothing more than a specification, a set of interfaces and annotations offered by Java EE. And then, of course, we have the implementations; some of the more well known are RESTEasy and Jersey.
Also, if you ever decide to build a JEE-compliant application server, the guys from Oracle will tell you that, among many other things, your server should provide a JAX-RS implementation for the deployed apps to use. That’s why it’s called Java Enterprise Edition Platform.
Another good example of specification and implementation is JPA and Hibernate.
2.1. Lightweight Wars
So how does all this help us, the developers? The help is in that our deployables can and should be very thin, letting the application server provide the needed libraries. This applies when developing a RESTful API as well: the final artifact should not contain any information about the used JAX-RS implementation.
Sure, we can provide the implementation (here‘s a tutorial for RESTeasy). But then we cannot call our application “Java EE app” anymore. If tomorrow someone comes and says “Ok, time to switch to Glassfish or Payara, JBoss became too expensive!“, we might be able to do it, but it won’t be an easy job.
If we provide our own implementation we have to make sure the server knows to exclude its own – this usually happens by having a proprietary XML file inside the deployable. Needless to say, such a file should contain all sorts of tags and instructions that nobody knows nothing about, except the developers who left the company three years ago.
2.2. Always Know your Server
We said so far that we should take advantage of the platform that we’re offered.
Before deciding on a server to use, we should see what JAX-RS implementation (name, vendor, version and known bugs) it provides, at least for Production environments. For instance, Glassfish comes with Jersey, while Wildfly or Jboss come with RESTEasy.
This, of course, means a little time spent on research, but it’s supposed to be done only once, at the beginning of the project or when migrating it to another server.
3. An Example
If you want to start playing with JAX-RS, the shortest path is: have a Maven webapp project with the following dependency in the pom.xml:
1
2
3
4
5
6
| < dependency > < groupId >javax</ groupId > < artifactId >javaee-api</ artifactId > < version >7.0</ version > < scope >provided</ scope > </ dependency > |
We’re using JavaEE 7 since there are already plenty of application servers implementing it. That API jar contains the annotations that you need to use, located in package javax.ws.rs. Why is the scope “provided”? Because this jar doesn’t need to be in the final build either – we need it at compile time and it is provided by the server for the run time.
After the dependency is added, we first have to write the entry class: an empty class which extends javax.ws.rs.core.Application and is annotated with javax.ws.rs.ApplicationPath:
1
2
3
| @ApplicationPath ( "/api" ) public class RestApplication extends Application { } |
We defined the entry path as being /api. Whatever other paths we declare for our resources, they will be prefixed with /api.
Next, let’s see a resource:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| @Path ( "/notifications" ) public class NotificationsResource { @GET @Path ( "/ping" ) public Response ping() { return Response.ok().entity( "Service online" ).build(); } @GET @Path ( "/get/{id}" ) @Produces (MediaType.APPLICATION_JSON) public Response getNotification( @PathParam ( "id" ) int id) { return Response.ok() .entity( new Notification(id, "john" , "test notification" )) .build(); } @POST @Path ( "/post/" ) @Consumes (MediaType.APPLICATION_JSON) @Produces (MediaType.APPLICATION_JSON) public Response postNotification(Notification notification) { return Response.status( 201 ).entity(notification).build(); } } |
We have a simple ping endpoint to call and check if our app is running, a GET and a POST for a Notification (this is just a POJO with attributes plus getters and setters).
Deploy this war on any application server implementing JEE7 and the following commands will work:
1
2
3
4
5
6
7
| curl http: //localhost :8080 /simple-jaxrs-ex/api/notifications/ping/ curl http: //localhost :8080 /simple-jaxrs-ex/api/notifications/get/1 curl -X POST -d '{"id":23,"text":"lorem ipsum","username":"johana"}' http: //localhost :8080 /simple-jaxrs-ex/api/notifications/post/ --header "Content-Type:application/json" |
Where simple-jaxrs-ex is the context-root of the webapp.
This was tested with Glassfish 4.1.0 and Wildfly 9.0.1.Final. Please note that the last two commands won’t work with Glassfish 4.1.1, because of this bug. It is apparently a known issue in this Glassfish version, regarding the serialization of JSON (if you have to use this server version, you’ll have to manage JSON marshaling on your own)
4. Conclusion
At the end of this article, just keep in mind that JAX-RS is a powerful API and most (if not all) of the stuff that you need is already implemented by your web server. No need to turn your deployable into an unmanageable pile of libraries.
This write-up presents a simple example and things might get more complicated. For instance, you might want to write your own marshalers. When that’s needed, look for tutorials that solve your problem with JAX-RS, not with Jersey, Resteasy or other concrete implementation. It’s very likely that your problem can be solved with one or two annotations.
Annotations in JAX-RS, explaining their use
1.1 @Path
PathAnnotation.java
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
| package com.javacodegeeks.examples.rest.annotations; import java.util.List; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import com.javacodegeeks.examples.rest.entites.Author; public class PathAnnotation { @GET @Produces ( "application/xml" ) @Path ( "javacodegeeks/authors" ) public List getAuthors() { // TODO: Code for returning list of authors return null ; } } |
1.2 @PathParam
This annotation is used to bind the parameter passed in the URI to the parameter in the REST method. Following is the example usage of
annotation.
PathParamAnnotation.java
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
| package com.javacodegeeks.examples.rest.annotations; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.PathParam; import javax.ws.rs.Produces; import com.javacodegeeks.examples.rest.entites.Author; public class PathParamAnnotation { @GET @Produces ( "application/json" ) @Path ( "javacodegeeks/authors/{id}" ) public Author getAuthor( @PathParam ( "id" ) int id) { // TODO: Code for returning author by id return null ; } } |
In the above code snippet parameter in curly braces is mapped to method parameter using
annotation.1.3 @GET
GetAnnotation.java
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
| package com.javacodegeeks.examples.rest.annotations; import java.util.List; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import com.javacodegeeks.examples.rest.entites.Author; public class GetAnnotation { @GET @Produces ( "application/xml" ) @Path ( "javacodegeeks/authors" ) public List getAuthors() { // TODO: Code for returning list of authors return null ; } } |
1.4 @POST
PostAnnotation.java
01
02
03
04
05
06
07
08
09
10
11
12
13
14
| package com.javacodegeeks.examples.rest.annotations; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import com.javacodegeeks.examples.rest.entites.Author; public class PostAnnotation { @POST @Consumes ( "application/json" ) public void addAuthor(Author contact) { //TODO: Code to store author } } |
1.5 @PUT
PutAnnotation.java
01
02
03
04
05
06
07
08
09
10
11
12
13
14
| package com.javacodegeeks.examples.rest.annotations; import javax.ws.rs.Consumes; import javax.ws.rs.PUT; import com.javacodegeeks.examples.rest.entites.Author; public class PutAnnotation { @PUT @Consumes ( "application/json" ) public void updateAuthor(Author contact) { //TODO: Code to update or add author } } |
1.6 @DELETE
DeleteAnnotation.java
01
02
03
04
05
06
07
08
09
10
11
12
13
| package com.javacodegeeks.examples.rest.annotations; import javax.ws.rs.DELETE; import javax.ws.rs.Path; import javax.ws.rs.PathParam; public class DeleteAnnotation { @DELETE @Path ( "javacodegeeks/authors/{id}" ) public void deleteAuthor( @PathParam ( "id" ) int id) { //TODO: Delete author with id passed as PathParam } } |
1.7 @Consumes
ConsumesAnnotation.java
01
02
03
04
05
06
07
08
09
10
11
12
13
14
| package com.javacodegeeks.examples.rest.annotations; import javax.ws.rs.Consumes; import javax.ws.rs.POST; import com.javacodegeeks.examples.rest.entites.Author; public class HeadAnnotation { @POST @Consumes ( "application/json" ) public void addAuthor(Author contact) { //TODO: Code to store author } } |
In the above code snippet, REST method is consuming resource having MIME type JSON.
1.8 @Produces
ProducesAnnotation.java
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
| package com.javacodegeeks.examples.rest.annotations; import java.util.List; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import com.javacodegeeks.examples.rest.entites.Author; public class ProducesAnnotation { @GET @Produces ( "application/json" ) @Path ( "javacodegeeks/authors" ) public List getAuthors() { // TODO: Code for returning list of authors return null ; } } |
In the above code snippet, REST method is returning response having MIME type JSON.
1.9 @QueryParam
QueryParamAnnotation.java
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
| package com.javacodegeeks.examples.rest.annotations; import java.util.List; import javax.ws.rs.GET; import javax.ws.rs.Path; import javax.ws.rs.Produces; import javax.ws.rs.QueryParam; import com.javacodegeeks.examples.rest.entites.Author; public class QueryParamAnnotation { @GET @Produces ( "application/json" ) @Path ( "javacodegeeks/authors" ) public List getAuthor( @QueryParam ( "name" ) String name, @QueryParam ( "age" ) int age) { // TODO: Calculate and return list of authors which match the criteria // of age and name return null ; } }
|
Introduction to @Consumes and @Produces
All resource methods can consume and produce content of almost any type. If you make a POST request to a URI, such as api/books, the REST API expects the HTTP body to contain a payload that represents the resource it should create.
This resource can be represented using any media type. Although typically, it will be represented in either, JSON or XML, but it could be plain text, binary or a custom format. It doesn’t matter, as long as there is a method in the resource class that can consume that media type.
Resource Method Selection
So, the question is: how does the resource class know the payload’s media type and how does it select the right method to deal with it? Well, in the header of the HTTP request, there is a content-type field that specifies the media type and on the other end, the server end, the resource class has a method annotated with the matching type.
So, for example: If a request has the content-type set to application/json the resource method that consumes this request is the method annotated with the same type, and likewise if the content type were application/xml the method annotated with MediaType APPLICATION_XML would handle that request.
Consume and Produce JSON
Just as a method can consume a payload of a given type, it can produce a response payload of a specific media type too. In the case of a POST request, the created resource can be returned back to the client. Conventionally, it is returned back in the same format as it was received. So returns back as JSON, if it was POSTed in JSON format, nevertheless, this does not have to be the case.
There is another HTTP header that specifies the accepted return media-type and there is a matching annotation on the resource method also. Such a method would be annotated with the @Produces annotation and passed the MediaType APPLICATION_JSON.
So a full example would be an HTTP POST request with a content-type of JSON and an accept type of JSON, and the corresponding resource method would be annotated appropriately with both a @Consumes and @Produces annotation with the MediaType APPLICATION_JSON.