End to End Restful API development using OpenAPI Specification

Ramesh Lingappa
Oct 23 · 7 min read
Image downloaded from the internet

With the increasing number of adoption towards service-oriented architecture and for better integrations with external systems, it became a necessity to write Restful APIs for our services. While building so we might often find several challenges such as,

  • Standard & Consistent API design
  • Better documentation
  • Client Libraries
  • Playground (better developer experience)

So while writing APIs, we have to make sure it sticks to a standard design principle, update documentation (hosted elsewhere) and finally write client libraries (harder if you have to support multiple languages). Doing all of this manually is a painful job.

Likely we have OpenAPI Specification (formerly known as swagger), which offers us a standard, language-agnostic interface to write RESTful APIs which allows both humans and computers to understand the service capabilities.

You can read more about it, there are plenty of content out there, here is the official site,

In short, you can define the APIs in a JSON or YAML file, which can be easily converted to code or documentation.

In this article, we will be looking at how we can work with OpenAPI specification, generate code and use it in the server & client-side.

Setting up:

For this example, we will be using java & gradle , but the idea is the same for other languages or environments. First, create a Gradle Java project petstore-api from the IDE of your choice, I use IntelliJ, Gradle 5.

A plain simple java project, you can also remove the java source folder from the project, since we are not going to write any code :). This project serves as a commonplace to hold the API contract (only definitions, no code) and libraries which can be used directly in the service where we write actual APIs as well as generate client libraries.

APIs:

For the API, we will be using the petstore sample provided in the OpenAPI site, it defines APIs to create & fetch pet's information.

Petstore sample OpenAPI spec

Create a new file petstore-api.yml under resources the folder and copy-paste the content from above either via gist or from Github.

Adding the OpenAPI Generator Plugin:

That’s the easy part, the official open API-generator repo contains information on how to use it, for gradle setup read on Gradle Plugin, copy-paste the following content to your build.gradle file,

openapi-generator setup

Here is the break down of the above code,

buildPetStoreJavaClient: This is a custom Gradle task which we extend from openApiGenerate task provided by the openapi-generator plugin, which is used to Generate code via Open API Tools Generator for Open API 2.0 or 3.x specification documents.

  • generatorName: represents which generator to use to build the code, we use java, there are several other generators available like Go, Koltin, Spring etc, take a look Generators List. So you can generate code for different languages, for clients or servers, etc.
  • there are several other configurations like the package name, artifact definitions etc can be configured, for more check Configurations
  • configOptions: this defines the configuration that needs to be passed to the generator, can vary for each generator, since in our case its java, we configure it to use java8 date library, Jackson for serialization, enable BeanValidation, etc. For more check Java Configurations

generateCode: I wrote a helper task which copies the generated documentation from the generated folder to the root docs folder so we can add it to git. Note: this task adds buildPetStoreJavaClient as it dependency

and we added the generateCode as a dependency to compileJava task, so every time we compile the code gets generated,

compileJava.dependsOn(generateCode)

Let's try, run compileJava task,

./gradlew clean compileJava

the code will be generated in build/java-client directory,

You can also notice it generated the entire project with its own project structure, build script, docs, readme, etc. you can configure these options in the generate task.

and finally, since the code is generated in the build directory, we need to add the code to current project sources in order to generate the jar, add the following code to your build.gradle file,

// attach the generated folder as source for this project
sourceSets {
main {
java {
srcDir "$buildDir/java-client/src/main/java"
}
}
}

Also now that your generated code is current project Source if you compile now you will get errors because the dependencies used by those codes were not defined in the current project, add the following.
NOTE: this is required purely for the sake of building the library.

// these dependencies are required for the generated code in order to build
ext {
swagger_annotations_version = "1.5.22"
jackson_version = "2.9.9"
jackson_databind_version = "2.9.9"
spring_web_version = "4.3.9.RELEASE"
jodatime_version = "2.9.9"
junit_version = "4.12"
validation_version = "2.0.1.Final"
}

dependencies {
compile "io.swagger:swagger-annotations:$swagger_annotations_version"
compile "com.google.code.findbugs:jsr305:3.0.2"
compile "org.springframework:spring-web:$spring_web_version"
compile "com.fasterxml.jackson.core:jackson-core:$jackson_version"
compile "com.fasterxml.jackson.core:jackson-annotations:$jackson_version"
compile "com.fasterxml.jackson.core:jackson-databind:$jackson_databind_version"
compile "com.fasterxml.jackson.jaxrs:jackson-jaxrs-json-provider:$jackson_version"
compile "com.fasterxml.jackson.datatype:jackson-datatype-jsr310:$jackson_version"
testCompile "junit:junit:$junit_version"
compile group: 'javax.annotation', name: 'javax.annotation-api', version: '1.3.2'
compile "javax.validation:validation-api:$validation_version"
}

So the complete build.gradle file should look like this,

complete build.gradle with openapi generator setup

And now for the moment of truth, when you run build command, you get the fancy java client library under bulid/libs,

./gradlew clean build
generated client library

You can upload the library to artifactory, maven central, GitHub etc for use by other developers or even for your own service (more on this later).

Similarly, you can generate libraries for other languages, so other developers can easily build code just by using the YAML API definition.

Complete source code for the api-contract with the setup is available on Github,

Making Changes to API:

Since the api definition is hosted in a separate repository, developers can easily make changes in different branches and create Pull Requests. So every change can be safely reviewed, checked for design quality and other stuff.
Now we can set up build pipelines to generate libraries, upload artifacts, update documentation all in one command.

Generating the Server Code:

What's more fun is, the openapi-generator can also generate server-side code using the same API definition (petstore-api.yml), which not only speeds up the development process but also helps the server to stick the same standard API definitions and conforms to it. So no more missing sync between the server API, its documentation and client implementation :)

Lets quickly set up a new project petstore-server and with the same build configuration with few changes to the generator,

I created it as a spring-boot app, but you can use any framework of your choice and generate API code accordingly.

petstore-server setup

My build.gradle file looks like this,

petstore-server build.gradle

if you check the buildPetStoreServerCode task, we use spring as our generator this time, and few changes related to this generator, most of it remains the same. Check our Spring generator configuration

Now we can simply create a controller PetsApiController which implements PetsApi interface generated by the open API-generation

Notice, the PetsApi, Pet model, Method Definitions all come from the generated code, our lives get much easier now!

The complete server code is available on Github,

Playground:

Yes, we get that one too. Swagger UI is an open-source UI for interacting with the OpenAPI definition file, we can host it ourselves or by using SwaggerHub.

We can also view it online, go to http://editor.swagger.io, copy-paste the API definition or Import from URL Petstore API Spec. You will get nice & fancy UI.

Conclusion

With OpenAPI specification we can able to,

  • Build APIs using API design-first approach,
  • Enforce server & client implementation to conform to the same definitions
  • Generate code for both clients & server implementation in several languages
  • Generate & keep documentation up to date with the API definitions
  • Have better developer experience with our APIs

OpenAPI have several other tools which you might be interested in, check out OpenAPI Tools

Happy building APIs…

Reference:

The Startup

Medium's largest active publication, followed by +528K people. Follow to join our community.

Ramesh Lingappa

Written by

Software Engineer @payconiq | rameshl.com

The Startup

Medium's largest active publication, followed by +528K people. Follow to join our community.

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade