REST API - Update resource partially Using HTTP PATCH verb

Representational state transfer (REST) is a stateless software architecture which is widely used in all sectors including mobile, cloud and social networking applications. REST service uses the standard HTTP methods(GET, POST, PUT, DELETE) for CRUD operations, which we called as verbs in REST architecture.

Generally we use these verbs,

  1. GET - to get the given resource from server
  2. POST - to create a new resource
  3. PUT - to update the existing resource
  4. DELETE - to delete the resource from server

For example, let say if you want to develop a REST service to create and manage profile. The profile contains first name, last name, email, phone number and address. usually, POST verb is used to create a new profile and PUT verb can be used to update the profile. Imagine, you want to develop a REST service to update only email or phone number. Which REST verb you will use? do you have a PUT verb in mind? if yes, noting wrong. We can use the PUT verb to update the field, but doesn't make sense because usually we use a PUT verb to update the complete profile not just for few fields.

Apart from standard HTTP methods, in March 2010 IETF introduced a non-standard HTTP method called PATCH (RFC5789) for REST services. The PATH verb is similar to PUT verb. PUT verb is used to update the existing resource completely, but the PATH verb is used to update the resource partially.

In the above example, we can use the PATCH verb to update the partial fields like updating only email or phone number.

Using Apache HttpClient

Below example show you how to use PATCH verb by using Apache HttpClient API.

The HTTP PATCH method will be supported from Apache Http-Components Client 4.2 onwards. With this version we can use HttpPatch class directly. See below example,

Map reqData=new HashMap();
reqData.put("email", "info@techjira.com");
		
StringEntity inputData=new StringEntity(new ObjectMapper().writeValueAsString(reqData),ContentType.APPLICATION_JSON);
		
HttpPatch httpPatch = new HttpPatch(new URI("http://api.techjira.com/user/123"));
httpPatch.setEntity(inputData);
		
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = httpClient.execute(httpPatch);

Maven dependency

<dependency>
    <groupId>org.apache.httpcomponents</groupId>
    <artifactId>httpclient</artifactId>
    <version>4.2+</version>
</dependency>

If you're using HttpClient with lower version of 4.2 we can't use the PATCH method until you use one of the below techniques.

Technique #1

This is a very simple technique to use. Hence the old version of HttpClient API doesn't have HttpPatch class, use HttpPost class along with _HttpMethod=PATCH query string parameter in the URL.

Map reqData=new HashMap();
reqData.put("email", "info@techjira.com");
		
StringEntity inputData=new StringEntity(new ObjectMapper().writeValueAsString(reqData),ContentType.APPLICATION_JSON);
		
HttpPost httpPatch = new HttpPost(new URI("http://api.techjira.com/user/123?_HttpMethod=PATCH"));
httpPatch.setEntity(inputData);
	
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = httpClient.execute(httpPatch);

There are some concerns with this approach that we need to pass extra parameter and may not work if the service provider doesn't allow extra parameters.

Technique #2

This is also similar to the technique #1 and the only difference is we don't pass the query string. Instead, we will override the getMethod() method of HttpPost class.

Map reqData=new HashMap();
reqData.put("email", "info@techjira.com");
		
StringEntity inputData=new StringEntity(new ObjectMapper().writeValueAsString(reqData),ContentType.APPLICATION_JSON);
		
HttpPost httpPatch = new HttpPost(new URI("http://api.techjira.com/user/123")){
	@Override
	public String getMethod() {
		return "PATCH";
	}
};

httpPatch.setEntity(inputData);
		
CloseableHttpClient httpClient = HttpClients.createDefault();
CloseableHttpResponse response = httpClient.execute(httpPatch);

Using Spring RestTemplate

Spring RestTempate class supports PATCH method only from 3.2 Version on words. Use below code if your using Spring 3.2 or above

String email="{\"email\":\"info@techjira.com\"}";
HttpEntity requestEntity = new HttpEntity(email);

// Create a new RestTemplate instance
RestTemplate restTemplate = new RestTemplate();

// Add the String message converter
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());

try {
    // Make the HTTP PATCH request 
    ResponseEntity response = restTemplate.exchange("http://api.techjira.com/user/123", HttpMethod.PATCH, requestEntity, String.class);
...
} catch (HttpClientErrorException e) {
	...
}

If your using RestTempate class from Spring 3.1 or lower version then there is an issue that this version doesn't support PATCH method. You can refer issue detail from link. Use Apache HttpClient API along with RestTempate class to solve this issue.

Note here the HttpClient API version is 4.2.

RestTemplate restTemplate = new RestTemplate();
CloseableHttpClient httpClient = HttpClients.createDefault()
HttpComponentsClientHttpRequestFactory requestFactory = new HttpComponentsClientHttpRequestFactory(httpClient);

restTemplate.setRequestFactory(requestFactory);

or You can define this through even in your bean xml file.

<bean id="httpClient" class="org.apache.http.impl.client.HttpClients" factory-method="createDefault"> </bean>
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
	 <constructor-arg>
     	<bean class="org.springframework.http.client.HttpComponentsClientHttpRequestFactory">
     	    <constructor-arg ref="httpClient"/>
         </bean>
     </constructor-arg>
</bean>

If you're using Apache HttpClient API 4.2 lower version, You can use technique #1 which I mentioned in this article.

Comments