RESTful Java Patterns and Best Practices

By Bhakti Mehta
  • Instant online access to over 7,500+ books and videos
  • Constantly updated with 100+ new titles each month
  • Breadth and depth in over 1,000+ technologies

About this book

The convergence of social networking, cloud computing, and the era of mobile applications has created a generation of emerging technologies that allow different networked devices to communicate with each other over the Internet with REST. REST has the benefits of being stateless; easing scalability, visibility, and reliability; and being platform and language agnostic.

This book is a practical, hands-on guide that provides you with clear and pragmatic information to take advantage of the real power of RESTful services and gives you a good foundation for using them in your applications. By comparing APIs from platforms such as Facebook, Twitter, GitHub, and PayPal, the book teaches a range of exciting capabilities with RESTful services and explores the infinite possibilities by using the diverse building blocks and tips covered in various chapters.

By the end of the book, you will be able to successfully use the concepts explained to design and implement applications based on best practices for RESTful services.

Publication date:
September 2014
Publisher
Packt
Pages
152
ISBN
9781783287963

 

Chapter 1. REST – Where It Begins

Web services in the traditional SOA formats have been around for a long time to implement heterogeneous communication between applications. One way to support this kind of communication is to use the Simple Object Access Protocol (SOAP)/Web Services Description Language (WSDL) approach. SOAP/WSDL is an XML-based standard and works well when there is a strict contract between the services. We are now in the era of distributed services where different clients from the Web, mobile, as well as other services (internal or external), can make use of APIs exposed by different vendors and open source platforms. This requirement enforces the need for easier exchange of information between distributed services along with predictable, robust, well-defined interfaces.

HTTP 1.1 is defined in RFC 2616, and is ubiquitously used as the standard protocol for distributed, collaborative hypermedia information systems. Representational State Transfer (REST) is inspired by HTTP and can be used wherever HTTP is used. This chapter will go over the basics of the RESTful services design and show how to produce and consume RESTful services, based on the standard Java API.

This chapter covers the following topics.

  • Introduction to REST

  • Safety and idempotence

  • Design principles for building RESTful services

  • Java Standard API for RESTful services

  • Best practices when designing RESTful services

 

Introduction to REST


REST is an architectural style that conforms to the web standards such as using HTTP verbs and URIs. It is bound by the following principles:

  • All resources are identified by the URIs

  • All resources can have multiple representations

  • All resources can be accessed/modified/created/deleted by standard HTTP methods

  • There is no state information on the server

REST and statelessness

REST is bound by the principle of statelessness. Each request from the client to the server must have all the details to understand the request. This helps to improve visibility, reliability, and scalability for requests.

Visibility is improved, as the system monitoring the requests does not have to look beyond one request to get details. Reliability is improved as there is no check-pointing/resuming in case of partial failures. Scalability is improved because the number of requests that can be processed by the server increases, as the server is not responsible for storing any state.

Note

Roy Fielding's dissertation on the REST architectural style provides details on the statelessness of REST. Check http://www.ics.uci.edu/~fielding/pubs/dissertation/rest_arch_style.htm for more information.

With this initial introduction to the basics of REST, we shall cover the different maturity levels and how REST falls in it in the following section.

 

The Richardson Maturity Model


The Richardson Maturity Model is a model developed by Leonard Richardson. It talks about the basics of REST in terms of resources, verbs, and hypermedia controls. The starting point for the maturity model is to use the HTTP layer as the transport. This is shown in the following diagram:

Level 0 – Remote Procedure Invocation

Level 0 contains SOAP or XML-RPC sending data as Plain Old XML (POX). Only the POST methods are used. This is the most primitive way of building SOA applications with a single POST method and using XML to communicate between services.

Level 1 – REST resources

Level 1 uses the POST methods and instead of using a function and passing arguments it uses the REST URIs. So, it still uses only one HTTP method. It is better than Level 0 as it breaks a complex functionality into multiple resources with the use of one POST method to communicate between services.

Level 2 – more HTTP verbs

Level 2 uses other HTTP verbs such as GET, HEAD, DELETE, and PUT along with the POST methods. Level 2 is the real use case of REST, which advocates using different verbs based on the HTTP request methods and the system can have multiple resources.

Level 3 – HATEOAS

Hypermedia as the Engine of Application State (HATEOAS) is the most mature level of Richardson's model. The responses to the client requests contain hypermedia controls, which can help the client decide what is the next action they can take. Level 3 encourages easy discoverability and makes it easy for the responses to be self-explanatory. There is debate about whether HATEOAS is truly RESTful because the representation contains more information beyond just describing the resource. We will show details on how some platforms such as PayPal have implemented HATEOAS as part of their APIs in Chapter 5, Advanced Design Principles.

The next section covers safety and idempotence, the two important terminologies when dealing with RESTful services.

 

Safety and idempotence


The following section discusses in detail what are safe and idempotent methods.

Safe methods

Safe methods are methods that do not change the state on the server. For example, GET /v1/coffees/orders/1234 is a safe method.

Note

Safe methods can be cached. GET and HEAD are safe methods.

The PUT method is not safe as it will create or modify a resource on the server. The POST method is not safe for the same reasons. The DELETE method is not safe as it deletes a resource on the server.

Idempotent methods

An idempotent method is a method that will produce the same results irrespective of how many times it is called.

Note

The GET method is idempotent, as multiple calls to the GET resource will always return the same response.

The PUT method is idempotent as calling the PUT method multiple times will update the same resource and not change the outcome.

POST is not idempotent and calling the POST method multiple times can have different results and will result in creating new resources. DELETE is idempotent because once the resource is deleted, it is gone and calling the method multiple times will not change the outcome.

 

Design principles for building RESTful services


Here is the process of designing, developing, and testing RESTful services. We will cover each of these in detail in this chapter:

  • Identifying the resource URIs

    This process involves deciding what nouns will represent your resource.

  • Identifying the methods supported by the resource

    This process involves using the various HTTP methods for CRUD operations.

  • Identifying the different representations supported by the resource

    This step involves choosing whether the resource representation should be JSON, XML, HTML, or plain text.

  • Implementing the RESTful services using JAX-RS APIs

    The API needs to be implemented based on the JAX-RS specification

  • Deploying the RESTful services

    Deploy the service on an application container such as Tomcat, Glassfish, and WildFly. The samples show how to create a WAR file and deploy on Glassfish 4.0 and it can work with any JavaEE 7-compliant container.

  • Testing the RESTful services

    Write the client API for testing the services or use curl-or-browser-based tools to test the REST requests.

Identifying the resource URIs

RESTful resources are identified by resource URIs. REST is extensible due to the use of URIs for identifying resources.

The following table shows sample URIs, which can represent different resources in the system:

URI

Description of the URI

/v1/library/books

This is used to represent a collection of book resources in a library

/v1/library/books/isbn/12345678

This is used to represent a single book identified by its ISBN "12345678"

/v1/coffees

This is used to represent all the coffees that are sold by a coffee shop

/v1/coffees/orders

This is used to represent all the coffees that are ordered

/v1/coffees/orders/123

This is used to represent a single order of coffee identified by "123"

/v1/users/1235

This is used to represent a user in a system identified by "1235"

/v1/users/5034/books

This is used to represent all the books for a user identified by "5034"

All the preceding samples show a clear readable pattern, which can be interpreted by the client. All these resources could have multiple representations. These examples of resources shown in the preceding table can be represented by JSON, XML, HTML, or plain text and can be manipulated by HTTP methods: GET, PUT, POST, and DELETE.

Identifying the methods supported by the resource

HTTP verbs comprise a major portion of the uniform interface constraint, which defines the association between the actions identified by the verb, to the noun-based REST resource.

The following table summarizes HTTP methods and descriptions for the actions taken on the resource with a simple example of a collection of books in a library.

HTTP method

Resource URI

Description

GET

/library/books

This gets a list of books

GET

/library/books/isbn/12345678

This gets a book identified by ISBN "12345678"

POST

/library/books

This creates a new book order

DELETE

/library/books/isbn/12345678

This deletes a book identified by ISBN "12345678"

PUT

/library/books/isbn/12345678

This updates a specific book identified by ISBN "12345678'

PATCH

/library/books/isbn/12345678

This can be used to do a partial update for a book identified by ISBN "12345678"

The next section will cover the semantics of each HTTP verb in the context of REST.

HTTP verbs and REST

HTTP verbs inform the server what to do with the data sent as part of the URL.

GET

The GET method is the simplest verb of HTTP, which enables us to get access to a resource. Whenever the client clicks a URL in the browser, it sends a GET request to the address specified by the URL. GET is safe and idempotent. The GET requests are cached. Query parameters can be used in GET requests.

For example, a simple GET request to retrieve all active users is as follows:

curl http://api.foo.com/v1/users/12345?active=true
POST

POST is used to create a resource. The POST requests are neither idempotent nor safe. Multiple invocations of the POST requests can create multiple resources.

The POST requests should invalidate a cache entry if it exists. Query parameters with the POST requests are not encouraged.

For example, a POST request to create a user can be as follows:

curl –X POST  -d'{"name":"John Doe","username":"jdoe", "phone":"412-344-5644"}' http://api.foo.com/v1/users
PUT

PUT is used to update a resource. PUT is idempotent but not safe. Multiple invocations of the PUT requests should produce the same results by updating the resource.

The PUT requests should invalidate the cache entry if it exists.

For example, a PUT request to update a user can be as follows:

curl –X PUT  -d'{ "phone":"413-344-5644"}'
http://api.foo.com/v1/users
DELETE

DELETE is used to delete a resource. DELETE is idempotent but not safe. This is idempotent because based on the RFC 2616, the side effects of N > 0 requests is the same as for a single request. This means once the resource is deleted, calling DELETE multiple times will get the same response.

For example, a request to delete a user can be as follows:

curl –X DELETE http://foo.api.com/v1/users/1234
HEAD

HEAD is similar to the GET request. The difference is that only HTTP headers are returned and no content is returned. HEAD is idempotent and safe.

For example, a request to send a HEAD request with curl is as follows:

curl –X HEAD http://foo.api.com/v1/users

Tip

It can be useful to send a HEAD request to see if the resource has changed before trying to get a large representation using a GET request.

PUT versus POST

According to RFC, the difference between PUT and POST is in the Request URI. The URI identified by POST defines the entity that will handle the POST request. The URI in the PUT request includes the entity in the request.

So, POST /v1/coffees/orders means to create a new resource and return an identifier to describe the resource. In contrast, PUT /v1/coffees/orders/1234 means to update a resource identified by "1234" if it exists; else create a new order and use the orders/1234 URI to identify it.

Note

PUT and POST can both be used to create or update methods. The usage of the method depends on the idempotence behavior expected from the method as well as the location of the resource to identify it.

The next section will cover how to identify the different representations of the resource.

Identifying the different representations of the resource

The RESTful resources are abstract entities, which need to be serialized to a representation before they can be communicated to the client. The common representations for a resource can be XML, JSON, HTML, or plain text. A resource can provide the representation to the client based on what the client can handle. A client can specify which language and media type it prefers. This is known as content negotiation. Chapter 2, Resource Design, covers the content negotiation topic in detail.

Implementing the APIs

Now that we have some idea on designing RESTful resources and associating HTTP verbs to take actions on the resources, we will cover what it takes to implement the APIs and build a RESTful service. This section will cover the following topic:

  • Java API for RESTful Services (JAX-RS)

The Java API for RESTful Services (JAX-RS)

The Java API for RESTful services provides portable APIs for building and developing applications based on the REST architectural style. Using JAX-RS, Java POJOs can be exposed as RESTful web resources, which are independent of the underlying technology and use a simple annotation-based API.

JAX-RS 2.0 is the latest version of the specification and has newer features compared to its predecessor JAX-RS 1.0, especially in the following areas:

  • Bean validation support

  • Client API support

  • Asynchronous invocation support

Jersey is the implementation of JAX-RS specification.

We will cover all these topics in detail in the subsequent chapters. We are demonstrating a simple coffee shop example where you can create a REST resource called CoffeesResource, which can do the following:

  • Give details of the orders placed

  • Create new orders

  • Get details on a specific order

To create a RESTful resource, we begin with a POJO called CoffeesResource. An example of a JAX-RS resource is shown as follows:

@Path("v1/coffees")
public class CoffeesResource {

    @GET
    @Path("orders")
    @Produces(MediaType.APPLICATION_JSON)
    public List<Coffee> getCoffeeList( ){
      //Implementation goes here

    }
  1. As shown in the preceding code, we create a small POJO called CoffeesResource. We annotate the class with @Path("v1/coffees"), which identifies the URI path this class serves requests for.

  2. Next, we define a method called getCoffeeList(). This method has the following annotations:

    • @GET: This indicates that the annotated method represents a HTTP GET request.

    • @PATH: In this example, the GET requests for v1/coffees/orders will be handled by this getCoffeeList() method.

    • @Produces: This defines the media types produced by this resource. In our preceding snippet, we define the MediaType.APPLICATION_JSON that has the application/json value.

  3. Another method to create an order is as follows:

        @POST
        @Consumes(MediaType.APPLICATION_JSON)
        @Produces(MediaType.APPLICATION_JSON)
        @ValidateOnExecution
        public Response addCoffee(@Valid Coffee coffee) {
        //Implementation goes here
        }

For the second method of creating an order, we defined a method called addCoffee(). This method has the following annotations:

  • @POST: This indicates that the annotated method represents the HTTP POST request.

  • @Consumes: This defines the media types consumed by this resource. In our preceding snippet, we define the MediaType.APPLICATION_JSON that has the application/json value.

  • @Produces: This defines the media types produced by this resource. In our preceding snippet, we define the MediaType.APPLICATION_JSON that has the application/json value.

  • @ValidateOnExecution: This specifies which methods should have their parameters or return values validated on execution. More details on the @ValidateOnExecution and @Valid annotations will be covered in Chapter 3, Security and Traceability.

Thus, we saw with a simple sample on how easy it is to convert a simple POJO to a REST resource. Now, we will cover the Application subclass, which will define the components of a JAX-RS application including the metadata.

The following is the code for a sample Application subclass named CoffeeApplication:

@ApplicationPath("/")
public class CoffeeApplication extends Application {

    @Override
    public Set<Class<?>> getClasses() {
        Set<Class<?>> classes = new HashSet<Class<?>>();
        classes.add(CoffeesResource.class);
        return classes;
    }

As shown in the preceding code snippet, the getClasses() method has been overridden and we add the CoffeesResource class to the Application subclass. The Application classes can be part of WEB-INF/classes or WEB-INF/lib in the WAR file.

Deploying the RESTful services

Once we have created the resource and added the meta-information to the Application subclass, the next step is to build the WAR file .The WAR file can be deployed on any servlet container.

The source for the samples is available as part of the downloadable bundle with this book, which will have detailed steps to deploy and run the samples.

Test the RESTful services

We can then use the Client API functionality provided by JAX-RS 2.0 to access the resources.

This section will cover the following topics:

  • Client API with JAX-RS 2.0

  • Accessing RESTful resources using curl, or a browser-based extension called Postman

The Client API with JAX-RS 2.0

JAX-RS 2.0 had newer Client APIs for accessing RESTful resources. The entry point of the client API is javax.ws.rs.client.Client.

With the newly introduced Client API in JAX-RS 2.0, the endpoint can be accessed as follows:

Client client = ClientFactory.newClient();
WebTarget target = client.target("http://. . ./coffees/orders");
String response = target.request().get(String.class);

As shown in the preceding snippet, the default instance of the client is obtained using the ClientFactory.newClient() method. Using the target method, we create a WebTarget object. These target objects are then used to prepare the request by adding the method and the query parameters.

Prior to these APIs, the way we would get access to REST resources was like this:

URL url = new URL("http://. . ./coffees/orders");
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setDoInput(true);
conn.setDoOutput(false);
BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String line;
while ((line = br.readLine()) != null) {
    //. . .
}

Thus, we can see how there has been an improvement in the JAX-RS 2.0 Client-side API support to avoid using HTTPURLConnection and instead use the fluent Client API.

If the request is a POST request:

Client client = ClientBuilder.newClient();
Coffee coffee = new Coffee(...);
WebTarget myResource = client.target("http://foo.com/v1/coffees");
myResource.request(MediaType.APPLICATION_XML) .post(Entity.xml(coffee), Coffee.class);

The WebTarget.request() method returns a javax.ws.rs.client.InvocationBuilder, which takes a post() method to invoke a HTTP POST request. The post() method takes an entity from the Coffee instance and specifies that the media type is "APPLICATION_XML".

A MessageBodyReaderWriter implementation is registered with the client. More on MessageBodyReader and MessageBodyWriter will be covered in Chapter 2, Resource Design.

The following table summarizes some of the main JAX-RS classes/annotations we covered so far.

Name of annotation

Description

javax.ws.rs.Path

This identifies the URI path that the resource serves a method for

javax.ws.rs.ApplicationPath

This is used by a subclass of Application as a base URI for all URIs supplied by the resources in application

javax.ws.rs.Produces

This defines the media type that the resource can produce

javax.ws.rs.Consumes

This defines the media type that the resource can consume

javax.ws.rs.client.Client

This defines the entry point for client requests

javax.ws.rs.client.WebTarget

This defines a resource target identified by the URI

Note

Clients are heavyweight objects that help facilitate the client-side communication infrastructure. It is therefore advised to construct only a small number of client instances in the application, as initialization as well as disposal of a client instance may be a rather expensive operation. Additionally, client instances must be properly closed before being disposed to avoid leaking resources.

Accessing RESTful resources

The following section covers the different ways REST resources can be accessed and tested by clients.

cURL

cURL is a popular command-line tool for testing REST APIs. The cURL library and the cURL command give the user the ability to create a request, put it on the pipe, and explore the response. The following are a few samples of curl requests for some basic functions:

curl request

Description

curl http://api.foo.com/v1/coffees/1

This is a simple GET request

curl -H "foo:bar" http://api.foo.com/v1/coffees

This is an example of a curl request for adding request headers using -H

curl -i http://api.foo.com/v1/coffees/1

This is an example of a curl command to view response headers using -i

curl –X POST -d'{"name":"John Doe","username":"jdoe", "phone":"412-344-5644"} http://api.foo.com/v1/users

This is an example of a curl request for a POST method to create a user

Even though cURL is extremely powerful, it has a lot of options to remember and use. Sometimes, it helps to use a browser-based tool to develop REST API such as Postman or Advanced REST client.

Postman

Postman on the Chrome browser is an excellent tool to test and develop REST API. It has a JSON and XML viewer for rendering the data. It can also allow previewing HTTP 1.1 requests, replay, and organize requests for future use. Postman shares the same environment as the browser and can display browser cookies too.

An advantage of Postman over cURL is that there is a nice user interface for entering parameters so that the user does not need to deal with commands or scripts. Various authorization schemes such as a basic user authentication and digest access authentication are also supported.

The following is a screenshot, which shows how to send queries in Postman:

As shown in the preceding screenshot, we see the Postman application. A simple way to test Postman is to launch the Postman Application from Chrome.

Then, select the HTTP method GET and paste the api.postcodes.io/random/postcodes URL. (PostCodes is a free, open source service based on geodata.)

You will see a JSON response like this:

{
    "status": 200,
    "result": {
        "postcode": "OX1 9SN",
        "quality": 1,
        "eastings": 451316,
        "northings": 206104,
        "country": "England",
        "nhs_ha": "South Central",
        "admin_county": "Oxfordshire",
        "admin_district": "Oxford",
        "admin_ward": "Carfax",
…}
}

Tip

Downloading the example code

You can download the example code files for all Packt books you have purchased from your account at http://www.packtpub.com. If you purchased this book elsewhere, you can visit http://www.packtpub.com/support and register to have the files e-mailed directly to you.

On the left pane of the preceding screenshot are different queries, which have been added to a collection like getting all the coffee orders, getting a specific order, creating orders, and so on based on testing the various samples in this book. You can create custom collections of queries similarly.

Note

For more details, check http://www.getpostman.com/.

Other tools

Here are some additional tools, which can be very useful when working with REST resources.

Advanced REST Client

Advanced REST Client is another Chrome extension based on Google WebToolkit, which allows the user to test and develop REST API.

JSONLint

JSONLint is a simple online validator that ensures the JSON is valid. When sending JSON data as part of requests, it is useful to validate if the format of the data conforms to the JSON specification. In such cases, the client can validate the input using JSONLint. For more details, check http://jsonlint.com/.

 

Best practices when designing resources


The following section highlights some of the best practices when designing RESTful resources:

  • The API developer should use nouns to understand and navigate through resources and verbs with the HTTP method, for example, the /user/1234/books is better than /user/1234/getBook URI.

  • Use associations in the URIs to identify subresources. For example, to get the authors for book 5678, for user 1234, use the following /user/1234/books/5678/authors URI.

  • For specific variations, use query parameters. For example, to get all the books with 10 reviews, use /user/1234/books?reviews_counts=10.

  • Allow partial responses as part of query parameters if possible. An example of this case is to get only the name and age of a user, the client can specify, ?fields as a query parameter and specify the list of fields that should be sent by the server in the response using the /users/1234?fields=name,age URI.

  • Have defaults for the output format for the response in case the client does not specify which format it is interested in. Most API developers choose to send JSON as the default response mime type.

  • Have camelCase or use _ for attribute names.

  • Support a standard API for counts, for example users/1234/books/count, in case of collections so that the client can get an idea of how many objects can be expected in the response.

    This will also help the client with pagination queries. More details on pagination will be covered in Chapter 5, Advanced Design Principles.

  • Support a pretty printing option, users/1234?pretty_print. Also, it is a good practice to not cache queries with a pretty print query parameter.

  • Avoid chattiness by being as verbose as possible in the response. This is because if the server does not provide enough details in the response, the client needs to make more calls to get additional details. That is a waste of network resources as well as counts against the client's rate limits. More details on rate limiting are covered in Chapter 5, Advanced Design Principles.

 

Recommended reading


The following links may be useful to review for more details:

 

Summary


In this chapter, we covered the fundamentals of REST, CRUD API, and how to design RESTful resources. We worked with JAX-RS 2.0-based annotations that can represent HTTP methods and Client APIs that can be used to target the resources. Additionally, we iterated the best practices when designing RESTful services.

The next chapter will dig deeper into the concepts covered here. We will also cover topics such as content negotiation, entity providers in JAX-RS 2.0, error handling, versioning schemes, and response codes in REST. We will look into techniques the server can use to send responses to the client using Streaming or Chunking.

About the Author

  • Bhakti Mehta

    Bhakti Mehta is the author of Developing RESTful Services with JAX-RS 2.0, WebSockets, and JSON, Packt Publishing, published in 2013. She has more than 13 years of experience in architecting, designing, and implementing software solutions on top of Java EE and other related technologies. She is passionate about open source software development and has been one of the founding members of GlassFish Open Source Application Server.

    Bhakti has a Bachelor's degree in Computer Engineering and a Master's degree in Computer Science. Her areas of research include architecting solutions for resiliency, scalability, reliability, and performance with respect to server-side technologies, web services, and cloud applications.

    Currently, Bhakti is a Senior Software Engineer at Blue Jeans Network. As part of her current role, she works on developing RESTful services that can be consumed by ISV partners and the developer community. She also works on the backend infrastructure and is responsible for performance, scalability, and reliability of the services.Bhakti is a regular speaker at different conferences and has authored numerous articles, blogs, and tech tips at different portals such as https://home.java.net/ and Dzone. In her spare time, she enjoys kickboxing, traveling, and reading.

    Bhakti's tweets can be followed at @bhakti_mehta.

    Browse publications by this author
Book Title
Access this book, plus 7,500 other titles for FREE
Access now