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,
Version 3.0.2 The key words “MUST”, “MUST NOT”, “REQUIRED”, “SHALL”, “SHALL NOT”, “SHOULD”, “SHOULD NOT”…
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.
For this example, we will be using
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.
For the API, we will be using the
petstore sample provided in the OpenAPI site, it defines APIs to create & fetch pet's information.
Adding the OpenAPI Generator Plugin:
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,
Let's try, run compileJava task,
./gradlew clean compileJava
the code will be generated in
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
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
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"
compile group: 'javax.annotation', name: 'javax.annotation-api', version: '1.3.2'
So the complete build.gradle file should look like this,
And now for the moment of truth, when you run build command, you get the fancy java client library under
./gradlew clean build
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.
My build.gradle file looks like this,
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,
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.
API Design for Teams in SwaggerHub Swagger Editor is one of the most powerful design tools for developers to define…
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…