Photo by Artur Aldyrkhanov on Unsplash
From API specifications to code with OpenAPI
Generating client and server source code
The API economy is on fire 🔥🔥🔥
It has been on fire for years. Applications need to talk, systems must exchange data, and business processes require the implementation of sophisticated workflows composing existing services and functions.
Fortunately, the OpenAPI initiative is playing a key role in defining, through the vast jungle of applications and tools, an open standard.
In this article… discover how OpenAPI is essential to deliver Developer Experience in the API ecosystem, learn which OpenAPI tools can be adopted to generate source code, see a demo of client and server side code generation.
OpenAPI and OpenAPI Tools: not exactly the same
OpenAPI
OpenAPI is the “Lingua Franca” in the API world. This is one of the best definitions you will find to understand the role the standard plays.
“Lingua Franca” was, back in the middle age, how countries and people, who spoke different languages, found a way to communicate for a very important reason: trading.
OpenAPI defines a common language (in a human and machine-readable format) that allows the different parties to understand each other.
A quick note about the history of OpenAPI: it started as Swagger (the 2 terms are used often interchangeably), created by the Wordnik team for again a very important reason: Developer Experience. The team, at that time, wanted to help developers understand and use APIs, therefore they created Swagger and paved the path for OpenAPI.
OpenAPI Tools
OpenAPI Tools is an initiative not affiliated with OpenAPI, but rather an umbrella of projects and tools built on top of the standard.
The main tools provided are:
Code Generator: how to generate code from an OpenAPI specification
Validator: validation of an OpenAPI file to ensure it meets the organisation API style guide and standards
Diff: comparison between different versions of the same OpenAPI file to highlight what has changed
Code Generator
The Code Generator is definitely the most popular of these tools and it has reached a wide adoption (14.6K Github stars).
The goal of the tool is, starting from a valid OpenAPI specification, to generate source code, either on the client or server side.
It supports 100+ languages and sometimes multiple frameworks for the same language (think of Java with support for Spring, RestEasy and Jersey).
OpenAPI Code Generator features  (Image by author)
The generator can also create configuration files (i.e. the Apache configuration file can be created from OpenAPI) and documentation in various formats (HTML, Markdown, etc…).
Finally, the tool can be used with its own CLI or through Docker. If you are in the Java world you are in luck: it is developed in Java so you can build it from the source and invoke the jar, or integrate the Maven or Gradle plugin.
The Adyen way of API
Before we dive into the technical details of the code generation I would like to touch on why the OpenAPI standard is important at Adyen and the role of the OpenAPI Code Generator.
From Specs to Code  (Image by author)
The code base in the internal repositories is annotated (to describe endpoints, data models and attributes) and processed by the OpenAPI generator. The OpenAPI files are generated and published to GitHub.
The specs are now public and available to everyone. We have then identified 3 ways of consuming those:
make them available to popular developer tools (Postman and SwaggerHub)
feed those to our own API Explorer, an environment where all developers working with the Adyen platform can access the latest documentation, including examples and an interactive space to test requests and responses
generate the source code of the Adyen SDKs
From specs to Go client
It is now time to see the OpenAPI Generator in action. We are going to create a Go client. Note how we set the language (-g go
) and the destination folder (-o tmp/gocodegen
).
openapi-generator-cli generate -i SampleProject.yaml \
-g go -p packageName=User -o tmp/gocodegen
The outcome is an initial implementation of a Go client that includes the code to invoke the endpoints, the model (mapping the request and response payloads) and some configuration code needed to set up the client and the connection details.
Go client in IntelliJ  ( image by author)
Source code templates
The code generation works out of the box because the OpenAPI generator provides a default implementation of the source code templates (one for each language and framework combination). Those templates basically define how the specific code is going to look, from the method signature to the default body implementation, comments, and so on.
Check out my previous article if you want to know more about Mustache templates, the logic-less templating framework used by OpenAPI Tools.
Mustache templates with OpenAPI specs
Best features of the OpenAPI code generationmedium.com
SDK developer workflow
The workflow of the SDK developer is different. The key aspect is that (part of) the code is generated with OpenAPI Generator.
After fetching and customising the default code templates the magic happens: the code is generated by the tool. This is followed by other development activities (integrating with the rest of the application, adding tests, etc..) until the library is ready to be released.
SDK workflow  (image by author)
Scenario 1
After a quick team celebration, a new API version is released: boom! Not to worry: the developers grab the latest specs and regenerate the code, develop, test and ship again.
Scenario 2
The new version of the API might require some changes to the templates, maybe there are new features that were not considered before. In this case, the developers first adjust the source code templates and then proceed with the steps discussed above.
From specs to Java server stubs
Let’s move on and generate the server-side code using Java and Springboot, in this case also customising the source code templates.
First step: fetch the default templates from the Github repository.
openapi-generator-cli author template -g spring -o tmp/myspringtemplate
The templates are now copied locally at tmp/myspringtemplate
. Go on and edit them, for instance, open api.mustache
and change the Java doc
/**
custom note: generated for a demo
* {{httpMethod}} {{{path}}}{{#summary}} : {{.}}{{/summary}}
{{#notes}}
* {{.}}
{{/notes}}
Let’s also alter the generated body of the method, open methodBody.mustache
and add some new code (for example we could check the API key in the header or something else).
{{^reactive}}
{{#examples}}
{{#-first}}
// check API key
// ...
{{#async}}
Onto the final step: kick off the code generation.
openapi-generator-cli generate -i SampleProject.yaml -g spring \
-p apiPackage=com.adyen.api -p modelPackage=com.adyen.model \
-p groupId=com.adyen -p artifactId=MySampleApp -p artifactVersion=v0.1 \
-p invokerPackage=com.adyen -p configPackage=com.adyen.configuration \
-t tmp/myspringtemplate -o tmp/javacodegen
There are several settings (in this example the Java project requires configuration like the package name, Maven attributes, etc…), but what it is important to note is that we want to use our custom templates (-t tmp/myspringtemplate
), we select the spring
generator and set the destination folder (-o tmp/javacodegen
).
Practices and challenges
As we have seen the workflow and development lifecycle are different when adopting a specification-driven code generation. There are surely several benefits as long as good practices are adopted and challenges are managed.
Generate, then re-generate
This is really crucial. Code should always be (re)generated from specifications and therefore avoid manual ad-hoc changes.
This can be achieved in 2 ways:
suitable templates: add to the templates the code you need so it will always be included during the generation
good design: define a clear separation between the code that is (re)generated and the parts that cannot be (i.e. business logic, specific configurations, integration tests maybe). Think about different layers, components or classes.
Model, services, skip files
It is definitely a good start to generating the model.
Mapping manually large JSON payloads to classes/structs is tedious and error-prone. Take advantage of the OpenAPI Generator and create the model automatically without forgetting or misspelling fields.
Next, generate the services (client calls or server stubs).
Skip what is not applicable to your project (i.e. some scripts that the generator might add) or the code you prefer to manage outside the automated process (for example sophisticated configuration code that is entangled with your existing application and frameworks). This is easily done by listing the files to skip in the .openapi-generator-ignore
file.
Templates can change
The latest version of OpenAPI Generator finally has the feature or fix you have been waiting for. But this version is no longer compatible with the source code templates you customised years ago. This might involve significant refactoring.
My advice is to stay on top of things: keep upgrading the OpenAPI Generator as new versions are released and deal with the changes incrementally.
Conclusions
We are giving developers documentation, code snippets, examples and working code. But they want and need more and better.
Requirements change often, businesses must adapt fast and developers need the best tools and support.
OpenAPI and its ecosystem can help us deliver on those promises as long as we stick to a few principles:
discoverability: can the relevant information be found easily?
simplicity: is the generated code clear and usable?
consistency: are the documentation, examples, and SDKs reflecting accurately the content of the OpenAPI specifications?
Developer Experience is a feeling developers have at a given time when using your API, tool or product, and therefore it will over time change. It requires ongoing investment and an open mindset: we are never done and there is always room for improvement.