1

What are the types of API versioning and How to implement them?

Samet Baskıcı
  • 1,090
  • 3
  • 13
  • 26
  • Your question is only about the Controller? What's it do? ... Also, this is opinion based, so your question is at risk of being closed – OneCricketeer Apr 22 '18 at 01:07
  • That would be a horrible way to handle versioning. You should have a single code base and version the output accordingly. Have a look at the GSON for versioning. – Raf Apr 22 '18 at 01:07
  • This is going to be opinion-based, but I've preferred grouping by version first (among other things, because those tend to be splittable into separate jars or microservices). – chrylis -cautiouslyoptimistic- Apr 22 '18 at 01:31
  • Please, take a look at how HTML is versioned. That is how REST APIs should handle versioning as well as the media-type is the important thing actually. Any proprietary API that does only exchange generic JSON messages bear the danger of tight coupling in it which is what REST actually tries to fix – Roman Vottner Apr 22 '18 at 02:31
  • what serves me very well is this: http://www.javapractices.com/topic/TopicAction.do?Id=205. The idea is to package not by technical layer, but by business features. – sschrass Apr 22 '18 at 08:58

1 Answers1

0

Just to be clear, since the question is very board hence this answer is by no means the only way to achieve project structure and versioning. There might be many other ways, I am just sharing what I have previously used as it is relevant.

Apparently there are different ways to structure your codebase namely

  • Layer-based project structure
  • Feature-based project structure

In Layer-based project structure your code is structured based on what different types of layers i.e. controller, service, etc you have whereas in Feature-based project structure your code is structured based on features of your system, read here for more info.

There are lots of resources available online that showcase different kind of package structure and I personally stick with layer-based project structure because I prefer to organize my codebase based on layers rather than features.

Project structure

One really easy way to get started with a project skeleton, is to look at some example Spring webapps. For example, I go to Spring Initializer and select the following

  • Project name (i.e. myproj)
  • Group name (i.e. com)
  • Select the modules (i.e. REST, JPA, etc.)
  • Generate

Now, I have a REST-based Spring Boot project that I can use as a skeleton to customize it as per my layers. You do not have to use Spring Boot but, what I am trying to showcase is that Spring Boot recommended project structure for REST web service.

I usually have the following layers

  1. controller
  2. dao
  3. service
  4. model
  5. dto
  6. exception
  7. validator
  8. util

And so on, here is a screenshot of how the project structure looks like

src/main/java structure

And the unit test package structure would look as follow, you can imagine how the rest of the test classes look like.

src/test/java

If you have integration test or would you refer to it end to end test in your java application itself then, you would need

src/integ-test/java 
src/integ-test/resources

Endpoint versioning

There might be different ways to version endpoints. One approach that I have previously used is GSON's versioning support and it might or might not work for you but, sharing it here anyway. If you have noticed in the above screenshot there are the following packages

com.myproj.dto.inbound 
com.myproj.dto.outbound 

DTO stands for Data Transfer Object and as shown above the UserInDTO.java is a representation of User.java object that comes in the request and you will be using it with @RequestBody in the endpoint in your controller. The UserOutDTO.java is a representation of the User.java object that goes out. When using DTOs

  • You can adopt different naming conventions for what the consumer of the system see and what you use in your model (i.e. User.java)
  • You can include and exclude fields in your outgoing and incoming DTOs without making unwanted changes to your model/business objects (i.e. User.java)

Now that you have DTOs and if you are using GSON then you can use it's Versioning feature to include and exclude fields in the UserOutDTO.java using annotations such as @Since(1.5) and @Until(2.3). Since GSON is a serialization/deserialization library or in other words it converts JSON to Java Object and vice versa, then it has the ability to include and exclude fields before the Object is converted to JSON and you can achieve way more with the help of writing serialization and deserialization adapters.

Here is a sample of UserOutDTO.java and how the fields are versioned to include and exclude after a certain version

public class UserOutDTO {
    @Expose
    @SerializedName("User id")
    private int id; 
    @Expose
    private String firstName; 
    @Expose
    private String lastName;

    /*
     * This field will become available for all requests coming for version 2.0 onwards. For a request before 
     * version 2.0 the address field won't be available.
     */
    @Expose
    @Since(2.0)
    private String address; 

    /*
     * This field will become available after version 3.0 an example when you extend your model
     */
    @Expose
    @Until(3.0) 
    private String nickname; 

    //Getters and Setters
}

I hope this help. You can also checkout this question, there are a lot of very helpful answers Package structure for a Java project?

Raf
  • 7,505
  • 1
  • 42
  • 59