REST API Best Practices — With Design Examples from Java and Spring Web Services
Tags: Web Services, Java, Spring Boot, API, Spring

Designing Great REST API is important to have great microservices. How do you design your REST API? What are the best practices?

You will learn

How do you design great REST API?

What should you think about when designing REST API?

What are the best practices in designing RESTful Web Services?

REST API

This is the last article in a series of articles on REST APIs:

Use A Consumer First Approach

Who is going to use your service? The Service Consumer.

Are you looking at it from the consumer perspective?

If you design an API, will your consumer be able to understand your API?

If you expose your resources, will the consumer be able to locate and access them?

Will the consumer be able to understand your URIs?

What is the type of service that you provide? Is it a mobile application, or is a web based application? What are the kinds of consumers you expect, and are these consumer types likely to change in the future?

If you implement something like HATEOAS, think about how your consumers would use it, before you implement it.

The most important thing is to have great documentation. Make things easy for your consumers, so that it saves your own time. The more consumers can do on their own, the less work there is for you.

Whenever you have a discussion or review meeting, put the requirements of the consumer first.

Use A Contract First Approach

What is a contract?

The creator of the web service is considered as the service provider. The application the consumes the web service is the service consumer.

A contract is an agreement between a service provider and a service consumer about a service.

In order the utilize the service well, the service consumer needs to understand the contract fully. A contract includes details of many aspects of the service, such as:

How to call the web service?

What transport is being used?

What are the request and response structures?

This is also called the service definition.

In a contract first approach, you define the service contract first, and only then implement the service.

Contract First With WSDL

For example, when you define SOAP web services, you use WSDL to define the contract.

WSDL defines what are the service endpoints, the operations that you are exposing, and the request and response structures.

Contract First With Swagger/Open API

When you use RESTful web services, Swagger is a popular tool used to document your web services.

Swagger allows you to define what are the resources you are exposing as part of your API. It includes the details of each operation, such as whether it consumes XML, JSON or both. The schema of the responses is also present there.

It also gives the details of the response codes it supports. You can also see that this particular resource, /jpa/users :

supports a GET operation. In fact also supports a POST operation:

The response schema if this resource is seen to be:

The definition of User is present in the Swagger contract as:

It includes a birthDate , an id , a name and an array of posts . Some fields also include a description field within them.

In a contract first approach, you create such a Swagger definition, either by hand or by using an application, before the service is implemented.

Advantages Of A Contract First Approach

By using a contract first approach, you are thinking about your consumers, and how they can use the service. You are initially not worrying about the implementation details.

If you give importance to the implementation early on, then technical details creedp into your service definition.

You need your service definition to be independent of the platform being used, be it Java, .NET or whatever.

Define Organizational Standards For REST API

An important reference for your organizational standards is YARAS.

YARAS stands for Yet Another RESTful API Standard. YARAS provides standards, guidelines and conventions to be followed while developing RESTful web services. It defines tips for things such as:

How you should name your services?

How you should structure your request and response?

How you should implement filtering, sorting, paging and other actions?

How you should approach versioning?

How you need to approach API documentation?

Have A Single Approach To Design Services

With RESTful web services , you need to address a lot of complex issues before you start designing them. All the things listed above need to be figured out.

As an organization, you don’t want teams that handle different resources, to approach things differently.

For example, it is not good to have Team-A adopt request parameter based versioning, and Team-B to use URI based versioning.

Therefore, it is important you have a clearly defined organizational standards to approach RESTful services.

Customizing YARAS To Organizational Needs

The good thing about YARAS is, it can be customized to meet the needs specific to an organization. For example, you can

Customize what the request and response bodies need to look like

Choose a specific kind of versioning system

Since YARAS is quite comprehensive in its coverage, you can be sure you haven’t missed out on any important decision.

Build A Standard Organization wide REST API Framework

The typical frameworks that are used to build RESTful web services in the Java world, are Spring MVC, Spring REST and JAX-RS.

If you build a organization specific framework/archetype/reference application adhering to the common organization standards on top of your preferred REST API framework, it would make it easy for teams to adhere to your standards.

Typical features include:

Request and response structures

Error handling

Filtering

Searching

Versioning

Support for mock responses

HATEOAS

A standard framework ensures a standard way of approaching service design and implementation across the organization.

Have Decentralized Governance Of REST APIs

Create an expert group of representatives from teams building REST API and form a governance team. The team is responsible for

Improving REST API standards

Building/Designing your REST API Frameworks

Make Great Use Of HTTP

Whenever you think RESTful web services, think HTTP.

HTTP has all the features that support you to build great web services.

Use Proper HTTP Request Methods

Think about the HTTP request methods that you need to make use of. When you think of implementing any operation, identify the resource on which it is to be performed, and then seek out the relevant HTTP request method. Are you retrieving a detail, creating something, updating something that exists, or deleting a thing that exists?

Use

GET for retrieving

POST for creating

PUT for updating

DELETE for deleting

PATCH for partial updates

Use Appropriate HTTP Response Status

When you implement an operation, make sure you return the correct response status.

For example, when a particular resource is not found, don’t throw a server exception, Instead, send out the appropriate response code in the response message, such as 404 .

When there is actually a server exception, send back a 500 code.

When there is a validation error, send the code for a bad request.

Focus On Representation

Each resource can have multiple representations — XML or JSON format. Service consumer can choose the representation of their choice.

The service returns three users when we submit a GET request to it. In this case, we receive the JSON representation of the resource /users .

When consumer does not specify a preferred representation, we use JSON.

Consumer can send an Accept header specify the representation.

The response body now has XML content:

Use Plurals

Always use plurals when you name resources.

Let’s look at a simple example. Suppose we have a service that hosts a users resource. The following describe to consumers how to access them:

Create a user: POST /users

Delete a user: DELETE /users/1

Get all users: GET /users

Get one user: GET /users/1

Prefering a plural users to user makes URI more readable.

For example, If we use /user instead of /users for the retreive - GET /user - does not convey the right message to the reader.

Have Great Documentation

Consumers need to understand how to make best use of the service, and and the best way to help them is by creating great documentation.

SOAP web services can utilize the functionality of WSDL, while RESTful web services have options of Swagger (now Open API Documentation Standard).

Choosing the format is just one part of generating good documentation. What also matters is putting in the right amount of information to be of assistance to the consumer.

The documentation needs to be complete, and should cover the following points:

What are the Request and Response Structures?

How the consumer needs to authenticate himself?

What are the usage limits?

Specify all the response message types, and the related status codes, that can be expected out of the service

Have A Common REST API Documentation Portal

A beneficial thing to do would be to have a common REST API documentation portal, across the organization. Have a look at one such portal:

Such a portal consolidates all the resources present in the organization. Having a user interface such as Swagger UI would have its added benefits. Using Swagger UI, you can actually look at the documentation in more detail:

This is usable even by non-technical users. The information seen here includes:

The expected response format

The content type

The response codes supported

Toy can also try out the format of the documentation, in a live request/response pair.

Support Versioning

Versioning brings in a lot of complexity for a web service. Maintaining several differing versions of the same web service is a pain. Try avoiding it, when possible.

However, in certain scenarios, versioning is unavoidable.

Let us start off by looking at an example service. Suppose we have initially defined a service to have a class named PersonV1 , in this manner:

This version of the class does not take into account that a name could have many sub-parts, such as first name and last name. Have a look a this:

The second version of the original class was updated to correct this anomaly:

We cannot migrate the entire service to use PersonV2 , immediately! There might be other consumers who are expecting responses in the format of PersonV1 .

This is where versioning is needed.

Let us now look at the options we have to version these two resources.

Use Different URIs

One option that we have is to use different URIs for these different resources. In the exampel code below, we use the URIs v1/person and v2/person to differentiate them:

If you execute a GET request for the resource v1/person :

You will get the information corresponding to v1 . For the other resource:

Use A Request Parameter

The second versioning method uses a request parameter:

To the URI /person/param , if we send a parameter with version=1 , then we return the resource of type PersonV1 :

For the same URI, a parameter with version=2 returns a resource of type PersonV2 :

This method is called request parameter versioning.

Use A Header

Another way you can do versioning is by specifying a header.

Here, we use a header named X-API-VERSION , and have labeled the URI as /person/header . When the header value is 1 , the resource of type PersonV1 is returned:

When its value is 2 , a resource of type PersonV2 is retrieved:

We are using an attribute on a request header, to perform the versioning for us.

Use The Accept Header

The last method for achieving versioning makes use of the Accept header.

If the consumer includes the first versioning information in the Accept header of the GET request, the following resource comes back:

Otherwise, the resource of type PersonV2 is returned:

This is called Accept Header Versioning, or Media Type Versioning, because mime types are the usually the contents of an Accept header.

Comparing The Versioning Techniques

We have so far seen four types of versioning techniques:

URI versioning

Request Param versioning

Header versioning

Media Type versioning

Which of these is the best one?

The truth is, there is no single answer to this question.

The fact of the matter is that different types of versioning are patronized by different internet giants.

URI versioning — Twitter

Request Param versioning — Amazon

Header Parameter versioning — Microsoft

Media Type versioning — GitHub

You need to evaluate these four choices, accroding to your specific needs. There are a number of important factors to consider:

URI Pollution : With URI versioning and request parameter versioning, we end up polluting the URI space. This is because we add prefixes and suffixes to the core URI strings. Header versioning avoids that.

: With URI versioning and request parameter versioning, we end up polluting the URI space. This is because we add prefixes and suffixes to the core URI strings. Header versioning avoids that. Misuse Of HTTP Headers : In the case of Header versioning and Media Type versioning, there is a misuse of HTTP headers, since they were not originally meant for versioning.

: In the case of Header versioning and Media Type versioning, there is a misuse of HTTP headers, since they were not originally meant for versioning. Caching : A resource is defined by its URI. However, if you are not using the URI to determine its version, but using a header-based mechanism, the versioning information cannot be cached. If HTTP caching is important to you, use the URI or Request Parameter versioning.

: A resource is defined by its URI. However, if you are not using the URI to determine its version, but using a header-based mechanism, the versioning information cannot be cached. If HTTP caching is important to you, use the URI or Request Parameter versioning. Browser Request Executability : Both Header and Media Type versioning need the use of tools such as Postman to execute the browser request. However, if the consumers of the service are not technically well versed, then URI or Request Parameter versioning would be preferable.

: Both Header and Media Type versioning need the use of tools such as Postman to execute the browser request. However, if the consumers of the service are not technically well versed, then URI or Request Parameter versioning would be preferable. API Documentation: You also need to think about how you want to document your APIs. The URI and Request Parameter versioning are easier to document than the other two versioning types.

Realize that there is no single perfect solution!

Think About Error Handling

When a consumer sends a request to a service, it is important that he gets the right response. Whenever something goes wrong, it is important to send an appropriate response.

When Consumer Requests a Non Existing Resource

If we send a GET request to search for an existing user, we get the following response:

If you search for a non-existent user:

What you get back is a status of 404 Not Found . This is good error handling, because it correctly identifies that the resource is not found, and does not return a Server Error.

Let’s now send a GET request to a non-existent URI:

You can see that you get a 404 Not Found . A wrong URL indicates a non-existent resource.

A Look At Important Response Statuses

200 — Success

404 — Resource Not Found

400 — Bad Request (such as validation error)

201 — Created

401 — Unauthorized (when authorization fails)

500 — Server Error

Error Details In Response Body

It helps if you have a standard exception structure when designing your service.

For specific errors, specific response structures can be returned to the consumer, and this can be a standard across the organization. Make sure that the error response is also readable to the consumers, without confusion.

USe Swagger or Open API Documentation

Swagger is one of the most popular documentation formats for RESTful web services. It is today supported by a wide variety of organizations, and used in a large number of services. We look at two main aspects of Swagger here:

The Swagger documentation format

Swagger UI, which enables you to look at the Swagger documentation in a visually pleasing manner

Swagger Documentation

Have a look at the following Swagger JSON:

At a high level, it looks very similar to a WSDL definition. it has several important attributes:

host : Where the service is hosted

: Where the service is hosted basePath : The path where the service is hosted

: The path where the service is hosted consumes : What kinds of requests are accepted

produces : What kinds of responses are generated

paths ” the different resources present In this case, you have several types of resources listed:

When you look at the Swagger documentation, you can quickly determine the resources that are present, the operations that are supported, and the operations that are relevant for each resource:

The resource /users supports both GET and POST operations. For GET , you can see the supported request and response types. You also see the different response types it has:

Notice that for a 200 response, a schema is also mentioned, as an array of User . User is part of the definitions section at the bottom of the document:

Swagger is completely independent of the technology you use to implement your RESTful web service. It is all basic JSON at work.

Introducing Swagger UI

Swagger is a great UI tool that is useful to visualize Swagger documentation for a RESTful web service. Have a look at the screen grab below:

Note that we have chosen a particular version of a web service to view its documentation. Here is the same screen in better detail:

When we come to the homepage, it describes the resources that are listed:

Also, the set of operations supported for the resource URLs can be seen:

When you click on the GET operation of a particular resource, you get its details:

You can see the Model Schema is described visually. The attributes birthDate , id , links , name and posts are also shown. You can also execute a sample request, and view the response:

Using Swagger (Open API Standard) Tools

The great thing about Swagger is there are a lot of tools available around it. Have a look at the following service which we had used earlier, to explain versioning:

Here’s a look at the automatically generated documentation for this service:

There is support in Swagger for both a contract-first approach, and a code-first approach.

Do check out our video on the same topic:

Summary

In this article, we had a look at best practices for building and designing RESTful web services.

Other Java and Web Development Resources