Enterprise Integration Zone is brought to you in partnership with:

Sr. Software Architect, Passionate about Open source Tools & Technologies. Expert in Enterprise Web Application Development using Java/J2ee Platform. Worked significantly on Enterprise Data Grid, Transactional Data Management, B2B Integration and Performance & Code Instrumentation. Senthil has posted 8 posts at DZone. You can read more from them at their website. View Full User Profile

REST-JSON Service Versioning – Simple approach

02.05.2013
| 4795 views |
  • submit to reddit

Problem Statement:

As a provider of a service, one is obliged to maintain different versions of a service. One of the possible reasons could be the existing consumers of the service doesn’t want to upgrade to newer version.

Given the above problem statement, the service provider would need to manage & maintain multiple execution path, Request & Response structure / objects.

Note: I have chosen Spring MVC + Jackson Library as software stack for the solution approach.

Ex:

1.  Service that returns an employee object, given an employee Id.

@RequestMapping(value="/employee/{id}", method=RequestMethod.GET)
public ResponseEntity<Employee> fetchEmployee(@PathVariable int id){

   //Business operation/search & employee object is responded

   return new ResponseEntity<Employee>(new Employee(), HttpStatus.OK);
}

2.  The Employee response object could look something like this,


public class Employee { private int employeeId; private String name; private long primaryNumber; public int getEmployeeId() { return employeeId; } public String getName() { return name; } public long getPrimaryNumber() { return primaryNumber; } setters... }

3.  Assume the above service (/employee/{id}) is of version 1.0 & you are expected to add a secondary number as part of the employee response object only for a specific set of consumers. This would mean the service will have two version (1.0 & 2.0) 1.0 without secondary number & 2.0 with secondary number part of the response.

4.  Typical nature of implementation is write another service & expose that to the new consumer, this would also mean duplication of request/response objects in this case employee class.

Solution:

Based on the problem statement the solution proposed below would introduce a seamless versioning of your REST services on JSON.

I have introduced a new type of annotation to indicate all the supported versions of a REST Service.

@Version(versions="1.0,2.0,3.0...")

1.  Service that needs to be version aware, will be annotated with the custom annotation as show below.

@RequestMapping(value="/employee/{id}", method=RequestMethod.GET)
@Version(versions="1.0,2.0")
public ResponseEntity<Employee> fetchEmployee(@PathVariable int id){

	//Business operation/search employee object is responded

        return new ResponseEntity<Employee>(new Employee(), HttpStatus.OK);
}

2.  It’s just one part of it, how to control the request/response object, by version?

I have introduced a custom annotation @Include & @Exclude, to indicate if a property in the JSON object needs to be included


@Include (versions="1.0,..") - Include property for given versions of the service
@Exclude (versions="1.0,..") - Exclude property for given versions of the service

public class Employee {

private int employeeId;
private String name;
private long primaryNumber;
private long secondaryNUmber;

	@Include (versions="2.0")
	public long getSecondaryNUmber () {
		return secondaryNUmber;
	}

	
	public int getEmployeeId() {
		return employeeId;
	}

	public String getName() {
		return name;
	}

	public long getPrimaryNumber() {
		return primaryNumber;
	}
	
}

3.  Part of the solution is to overwrite JsonSerialize & JsonDeserialize to read the appropriate tags above to interpret the versions & form the request / response.

4.  Now Consumer has the responsibility to communicate the version of interest, which will be passed as request header attribute “version:1.0” or “version:2.0” etc.

Conclusion:

I have a working solution that I am thinking of open sourcing in a week or two, this article is more to get a feedback on the problem statement & your thoughts on my solution approach.

PS:

1.  Similar approach can be used for REST service on XML (with java Bindings) with some overwrites on XML serialize & de-serialize.

Published at DZone with permission of its author, Senthil Balakrishnan.

(Note: Opinions expressed in this article and its replies are the opinions of their respective authors and not those of DZone, Inc.)

Comments

Pavel Kotlov replied on Wed, 2013/02/13 - 5:50am

 It's a smart solution for the duplication Problems in case of small changes. If you face bigger changes in your payload you will be still forced to duplicate the code.

Senthil Balakrishnan replied on Wed, 2013/02/13 - 5:44pm in response to: Pavel Kotlov

Pavel,

I completely agree with you, this can get really complicated in real business scenarios of versioning. Even though, the business logic can be different for different versions, bare minimum this approach will help in using same domain object.

Sachin Deokar replied on Tue, 2014/03/04 - 12:01pm

 Hi,

Were you able to open source this code? I have a similar requirement and wanted to try out your suggestion.

Thanks,

Sachin

Tejas Patel replied on Tue, 2014/06/24 - 1:09am

Can I have the source code for this? . It would really help me. 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.