Spring Boot: API First Design

Advantages of API first approach

As we are adopting microservice-based architectures, API first approach have been gaining some traction. There are quite many advantages to using API first approach and I will discuss a few of them.

  • Well Documented API
    You follow a well-structure documentation of the API you are providing and it helps stake holders to have clear understanding of the interface you are providing via you APIs in a human-readable format.
  • Promotes Development in Parallel
    The producer and consumer of the API can work in parallel once you have the API definition in place. The consumer or producer can easily create mocks with the already agreed API contract and start their end of the development.

Let’s Get Started!

To start off, I went to https://editor.swagger.io/ and created my API definition. I used the Open API 3 specification to create the API definition. There are many other tools to create API definitions, but I choose this as I was familiar with creating Swagger API documentation in Java. I used this online editor as it provides auto-complete feature (with ctrl + space) depending on the context you are in. This helped me a lot to create the API definition.

API definition

Generating Code.

With the API definition all set, Let’s start with creating the server and client of the API. For this I created a spring boot application which I created normally via https://start.spring.io. The only dependency I added here was spring-web .

Server-Side Code Generation

To create the server-side code from the API definition, I added the Open API generator plugin and provided it with the API definition file. Since I am creating a server based on spring, I provided a generation type spring, So that it knows it can use spring classes to create my server code. There are quite a few server code generators that you can find here. Now, Let's look at what the plugin config looks like:

<dependency>
<groupId>javax.validation</groupId>
<artifactId>validation-api</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox-version}</version>
</dependency>
<dependency>
<groupId>org.openapitools</groupId>
<artifactId>jackson-databind-nullable</artifactId>
<version>${jackson-databind-nullable}</version>
</dependency>
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
<version>${swagger-annotations-version}</version>
</dependency>

Client Code Generation

For the client-side code generation, I use the same plugin, but this time with the generator name as java .

<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>${gson.version}</version>
</dependency>
<dependency>
<groupId>io.swagger.core.v3</groupId>
<artifactId>swagger-annotations</artifactId>
<version>${swagger-annotations-version}</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>${springfox-version}</version>
</dependency>
<dependency>
<groupId>com.squareup.okhttp3</groupId>
<artifactId>okhttp</artifactId>
<version>${okhttp.version}</version>
</dependency>
<dependency>
<groupId>com.google.code.findbugs</groupId>
<artifactId>jsr305</artifactId>
<version>${jsr305.version}</version>
</dependency>
  • For spring generator, there is some unused import from spring data that get added by the generator while creating the controller. Hence you would have to add spring data dependency, Even if you not using a database with the service. This may not be a big problem, because mostly you would have a database that you connect to with your service. You can check the current open bug here.
  • Usually, you would define the schema for request and response in the components section of the API definition file and then use the reference to these schemas in the API using the $ref: property. This is currently not working as excepted. The way to get around it was to define inline schema for each request and response. Hence the model names get generated with a prefix Inline* . You can track this bug here.

--

--

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Amrut Prabhu

Amrut Prabhu

Software Craftsman, Tech Enthusiast. I run https://refactorfirst.com to post all my articles