<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" ><generator uri="https://jekyllrb.com/" version="3.9.0">Jekyll</generator><link href="https://polak.ro/feed.xml" rel="self" type="application/atom+xml" /><link href="https://polak.ro/" rel="alternate" type="text/html" /><updated>2021-04-17T17:45:52+00:00</updated><id>https://polak.ro/feed.xml</id><title type="html">Piotr Polak - Software Engineer</title><subtitle>Piotr Polak - Software Engineer - personal site</subtitle><entry><title type="html">Best practices when maintaining SDK-friendly OpenAPI contracts</title><link href="https://polak.ro/2021/04/08/best-practices-when-maintaining-sdk-friendly-openapi-contracts.html" rel="alternate" type="text/html" title="Best practices when maintaining SDK-friendly OpenAPI contracts" /><published>2021-04-08T15:52:56+00:00</published><updated>2021-04-08T15:52:56+00:00</updated><id>https://polak.ro/2021/04/08/best-practices-when-maintaining-sdk-friendly-openapi-contracts</id><content type="html" xml:base="https://polak.ro/2021/04/08/best-practices-when-maintaining-sdk-friendly-openapi-contracts.html">&lt;p&gt;This document is a followup to &lt;a href=&quot;/2021/04/02/api-first-and-code-generation-done-right.html&quot;&gt;API First and code generation done right&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In order to make the code generation tools adoption successful it is very important to maintain high flexibility and
great attention to backward compatibility of the OpenAPI contact changes. An unsuspicious modification in the contract
metadata might break existing code even though the HTTP API contract is untouched.&lt;/p&gt;

&lt;h2 id=&quot;rules-for-developing-sdk-friendly-openapi-contracts&quot;&gt;Rules for developing SDK-friendly OpenAPI contracts&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;Respect Design First principle — think about all the API names, DTO names, data structures, operationIds, and
parameter list upfront.&lt;/li&gt;
  &lt;li&gt;When designing an API try to make it reusable, assume that your services will be consumed by multiple clients such as
web applications, mobile clients, or even applications that you are not yet aware of.&lt;/li&gt;
  &lt;li&gt;Treat &lt;strong&gt;contracts as contracts&lt;/strong&gt; — a small change in the OpenAPI definition might lead to massive changes in the
client code. Think of it as interface/binary compatibility. If you wouldn’t change your library’s interface method
signature, you probably wouldn’t like to change the endpoint definition as both would lead to broken code at the
library/SDK clients.&lt;/li&gt;
  &lt;li&gt;Assign operationId as if they were &lt;strong&gt;repository&lt;/strong&gt; methods and don’t change it over time. Whatever you define as
operationId will become the SDK method name. For example: getUsers, getUser, saveUser, deleteUser.&lt;/li&gt;
  &lt;li&gt;Make sure operationIds are unique to make sure client SDK can be built for any language (some languages do not support
method overloading).&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Assign DTO names according to the business domain. Try to apply the same naming convention as if DTOs would be your
business entities — this is not always possible, especially with some aggregate objects. Skip all the DTO-like
prefixes as these can be added by the code generator.&lt;/p&gt;

    &lt;p&gt;Example DTO names: User, PhoneNumber, Cart.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Generate SDKs often and see if you find the generated code developer-friendly.&lt;/li&gt;
  &lt;li&gt;Consider writing tests using your SDKs — if your tests fail to compile after a definition change, they will probably
make a bad impression on your clients also.&lt;/li&gt;
  &lt;li&gt;Provide good examples of the request and response payloads. The payload values should ideally satisfy all the
validation constraints so that they can be used during demo. Keep response payloads as close to production values as
possible as these can be used to generate your service stub/mock.&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Piotr Polak</name></author><summary type="html">This document is a followup to API First and code generation done right.</summary></entry><entry><title type="html">API First and code generation done right</title><link href="https://polak.ro/2021/04/02/api-first-and-code-generation-done-right.html" rel="alternate" type="text/html" title="API First and code generation done right" /><published>2021-04-02T15:52:56+00:00</published><updated>2021-04-17T17:38:00+00:00</updated><id>https://polak.ro/2021/04/02/api-first-and-code-generation-done-right</id><content type="html" xml:base="https://polak.ro/2021/04/02/api-first-and-code-generation-done-right.html">&lt;p&gt;This document is written from a Java/Fullstack developer perspective and it is intended to explain API First approach
from the business, consumer, and API creator points of view.&lt;/p&gt;

&lt;h2 id=&quot;some-historical-background&quot;&gt;Some historical background&lt;/h2&gt;

&lt;p&gt;In past days &lt;abbr title=&quot;Hypertext Transfer Protocol&quot;&gt;HTTP&lt;/abbr&gt; APIs used to be either random collections of &lt;abbr title=&quot;Remote Procedure Call&quot;&gt;RPC&lt;/abbr&gt;-like endpoints of some heavy &lt;abbr title=&quot;Simple Object Access Protocol&quot;&gt;SOAP&lt;/abbr&gt; interfaces.&lt;/p&gt;

&lt;p&gt;Some time around 2000 Roy Fielding presented &lt;abbr title=&quot;Representational state transfer&quot;&gt;REST&lt;/abbr&gt; in his doctoral dissertation but it took some time
before it was adopted as a common practice.&lt;/p&gt;

&lt;p&gt;For the enterprise world &lt;abbr title=&quot;Simple Object Access Protocol&quot;&gt;SOAP&lt;/abbr&gt; was a default choice as an integration protocol as it had a great advantage over &lt;abbr title=&quot;Representational state transfer&quot;&gt;REST&lt;/abbr&gt;&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;&lt;abbr title=&quot;Simple Object Access Protocol&quot;&gt;SOAP&lt;/abbr&gt; web services were formally defined by &lt;strong&gt;machine-readable description language&lt;/strong&gt; - &lt;abbr title=&quot;Web Services Description Language&quot;&gt;WSDL&lt;/abbr&gt;&lt;/li&gt;
  &lt;li&gt;which allowed the code generation tools to take care of all the &lt;strong&gt;glue code&lt;/strong&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;abbr title=&quot;Simple Object Access Protocol&quot;&gt;SOAP&lt;/abbr&gt; was not widely adopted by web and mobile applications due to its implementation complexity and high verbosity.&lt;/p&gt;

&lt;figure&gt;
  
&lt;img src=&quot;/assets/2021-04-02-api-first-done-right/the-internet.jpg&quot; alt=&quot;The Internet&quot; /&gt;

  &lt;figcaption&gt;
This is the Internet
&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h3 id=&quot;the-adaptation-of-swagger-and-the-swaggerui&quot;&gt;The adaptation of Swagger and the SwaggerUI&lt;/h3&gt;

&lt;p&gt;In 2011 Tony Tam created an open-sourced Swagger API. In the early days, Swagger was mostly used together with a
Swagger UI console that provided an attractive self-documenting API playground.&lt;/p&gt;

&lt;p class=&quot;notice--info&quot;&gt;&lt;strong&gt;This was and still is a great way to visually judge the clarity of an API.&lt;/strong&gt;&lt;/p&gt;

&lt;p class=&quot;notice--info&quot;&gt;&lt;strong&gt;Having Swagger UI available to test the API in the development environment makes the development flow developer friendly.&lt;/strong&gt;&lt;/p&gt;

&lt;figure&gt;
  
&lt;img src=&quot;/assets/2021-04-02-api-first-done-right/swagger-ui.jpg&quot; alt=&quot;Swagger UI&quot; /&gt;

  &lt;figcaption&gt;
SwaggerUI as an API playground.
&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;h3 id=&quot;adding-swaggerui-to-existing-projects&quot;&gt;Adding SwaggerUI to existing projects&lt;/h3&gt;

&lt;p&gt;Many projects that retrofittedd Swagger UI to previously existing projects, usually derived the API definition
by scanning the existing source code. Or in the worst case maintaining source code and the Swagger definition independently.&lt;/p&gt;

&lt;figure&gt;
  
&lt;img src=&quot;/assets/2021-04-02-api-first-done-right/swagger-annotations-in-code.jpg&quot; alt=&quot;Swagger annotations in code&quot; /&gt;

  &lt;figcaption&gt;
Swagger/OpenAPI metadata annotations in code (marked in red). These annotations serve no purpose at the application runtime.
@Api* annotations belong to the Swagger 2.0 package (described later).
&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Despite the multiple advantages, the approach where the API definition is just a second class citizen has some
non-obvious shortcomings:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Nonneterministic Swagger specification generation&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;There are many generator tools each of them providing different output for the same input.
For example the Maven build-time plugin that I used in the past could not handle custom/complex POST payload
examples thus limiting the attractiveness of my API. Learning this after I invested days in the development was not a
pleasant experience.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;The implementation diverging from the Swagger specification&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;Having the definition derived from code, sometimes it happens that what you have in your API definition is far away
from the actual service behavior (for example when you use implicit headers or argument resolvers in Spring MVC).&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Slower application startup&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;Some generators such as SpringFox build the definition at the application startup. Classpath scanning might take some
time if incorrectly configured.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;Metadata annotations leaking into the business code&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;The code is spoiled with additional metadata annotations and delivery artefact is bloated with an additional
dependency  that provides no additional business value when deployed to production.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Swagger later became what we now know as OpenAPI 3.0, currently there are two incompatible Java annotation packages:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;Swagger 2.0: &lt;a href=&quot;https://mvnrepository.com/artifact/io.swagger/swagger-annotations&quot;&gt;https://mvnrepository.com/artifact/io.swagger/swagger-annotations&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;OpenAPI 3.0: &lt;a href=&quot;https://mvnrepository.com/artifact/io.swagger.core.v3/swagger-annotations&quot;&gt;https://mvnrepository.com/artifact/io.swagger.core.v3/swagger-annotations&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;api-first&quot;&gt;API First&lt;/h2&gt;

&lt;p&gt;With this approach &lt;strong&gt;the API comes first&lt;/strong&gt; and then comes the implementation.
In other words &lt;strong&gt;the source code is no longer the API’s source of truth&lt;/strong&gt;.&lt;/p&gt;

&lt;h3 id=&quot;api-first---the-mental-shift&quot;&gt;API First - the mental shift&lt;/h3&gt;

&lt;p&gt;Developers no longer assume who their client is, whether it is an existing site, a desktop app,
or just a product that has not yet been created.&lt;/p&gt;

&lt;p&gt;If for some reason developers decide they don’t like the contract, &lt;strong&gt;changes at the design phase are cheaper by a couple
orders of magnitude&lt;/strong&gt; than in the scenario when the contract is defined by an already developed implementation.&lt;/p&gt;

&lt;p class=&quot;notice--info&quot;&gt;&lt;strong&gt;With the API First approach, your OpenAPI file becomes a contract and takes precedence over the code — both server 
(skeleton) and client SDKs are now derived from that contract.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;A typical server development flow:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Gather requirements and design the API&lt;/li&gt;
  &lt;li&gt;Lint the API against company standards/get feedback/review/improve&lt;/li&gt;
  &lt;li&gt;Generate code:
    &lt;ul&gt;
      &lt;li&gt;server skeleton&lt;/li&gt;
      &lt;li&gt;client SDKs&lt;/li&gt;
      &lt;li&gt;generate stubs/mocks for your clients to start the integration&lt;/li&gt;
    &lt;/ul&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Advantages (for the business):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Shorter time to market&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Parallel development flow and shorter feedback loop&lt;/p&gt;

    &lt;p class=&quot;notice--info&quot;&gt;Client application/frontend application can be developed independently on the development of the server application.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Great potential of building additional value on top of the APIs designed with versatility in mind&lt;/li&gt;
  &lt;li&gt;Gaining a competitive advantage by allowing the customers to build their products and tools on top of well designed APIs.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Advantages (for the creator and consumer):&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Infrastructure glue code doesn’t have to be written by hand - more time for the business logic development&lt;/li&gt;
  &lt;li&gt;Improved API quality and consistency across multiple products of the same family&lt;/li&gt;
  &lt;li&gt;No need to maintain dedicated client SDKs parallel to the server code&lt;/li&gt;
  &lt;li&gt;Reduced cognitive complexity - when using a generated SDK, from the client point of view,
remote services can be handled as if they were some local repositories&lt;/li&gt;
  &lt;li&gt;Improved developer confidence and satisfaction&lt;/li&gt;
&lt;/ul&gt;

&lt;h2 id=&quot;code-generation&quot;&gt;Code generation&lt;/h2&gt;

&lt;p&gt;Having OpenAPI as a machine-readable API definition made it possible to avoid human-developed API glue code
and it’s &lt;strong&gt;costly maintenance&lt;/strong&gt; (sometimes done independent for each component and each supported language).&lt;/p&gt;

&lt;p&gt;The tools can be used to generate:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;the &lt;strong&gt;client SDKs&lt;/strong&gt; for various languages and language flavours&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;the backend service skeleton&lt;/strong&gt;&lt;/li&gt;
  &lt;li&gt;&lt;strong&gt;the service mocks&lt;/strong&gt; (useful during the client app development)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Code generation is actually the first place where &lt;strong&gt;API First approach unleashes the full power&lt;/strong&gt; - it indirectly
enforces the contract continous valibility as any backward incompatible change must start with a highly visible
OpenAPI file change (as opposed to an inconspicuous code modification).&lt;/p&gt;

&lt;h3 id=&quot;code-generation-tools&quot;&gt;Code generation tools&lt;/h3&gt;

&lt;p&gt;There are two most popular code generation tools:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/OpenAPITools/openapi-generator&quot;&gt;https://github.com/OpenAPITools/openapi-generator&lt;/a&gt; (&lt;strong&gt;recommended&lt;/strong&gt;)&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://github.com/swagger-api/swagger-codegen&quot;&gt;https://github.com/swagger-api/swagger-codegen&lt;/a&gt; (the original project)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;They are both written in Java and support code generation for over 50 different languages and flavors.&lt;/p&gt;

&lt;p&gt;The generators can be used:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;from a command line&lt;/li&gt;
  &lt;li&gt;as build system plugins (Maven, Gradle)&lt;/li&gt;
  &lt;li&gt;as wrappers (NPM tools)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The generator tools define some &lt;a href=&quot;https://openapi-generator.tech/docs/configuration/&quot;&gt;common configuration options&lt;/a&gt;,
additionally each supported language provides a different set of configurable parameters.&lt;/p&gt;

&lt;p class=&quot;notice--info&quot;&gt;A complete of all the generators and the supported options can be found at &lt;a href=&quot;https://openapi-generator.tech/docs/generators&quot;&gt;https://openapi-generator.tech/docs/generators&lt;/a&gt;.&lt;/p&gt;

&lt;h3 id=&quot;code-generation-in-a-project-lifecycle&quot;&gt;Code generation in a project lifecycle&lt;/h3&gt;

&lt;p&gt;Code generation can be done either:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;during the &lt;strong&gt;project build&lt;/strong&gt; stage&lt;/p&gt;

    &lt;p&gt;Code generation is part of the project build (Maven/Gradle/NPM). Generated files are kept outside version control
(&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;target/generated&lt;/code&gt; for Maven or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;build/generated&lt;/code&gt; for Gradle), the source is included during the compilation phase.
This approach allows for greater code generation tuning and simpler CI/CD pipelines at the cost of the build time.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;as &lt;strong&gt;independently released libraries&lt;/strong&gt; released using a dedicated pipeline&lt;/p&gt;

    &lt;p&gt;Client SDKs are released independently and used as external dependencies (JARs for Java, NPM packages for JavaScript).
This approach makes project build faster at the cost of limited flexibility.
In case of the frontend application builds it allows avoiding mixing frontend build technologies with Java tools.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;generating-server-skeleton---spring-boot&quot;&gt;Generating server skeleton - Spring Boot&lt;/h3&gt;

&lt;p&gt;Generating server skeleton in a typical Spring Boot application means that you let the generator generate DTOs and the
controller interfaces — all you need to do is to implement these interfaces with concrete controllers.&lt;/p&gt;

&lt;figure&gt;
  
&lt;img src=&quot;/assets/2021-04-02-api-first-done-right/api-interface.jpg&quot; alt=&quot;API Interface&quot; /&gt;

  &lt;figcaption&gt;
Generated controller interface ready to be implemented by a concrete class.
When the API contract changes, so does the (programming) interface.
&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p class=&quot;notice--info&quot;&gt;The DTOs and controller interfaces are usually derived at the build time and &lt;strong&gt;kept outside the version control&lt;/strong&gt;.&lt;/p&gt;

&lt;figure&gt;
  
&lt;img src=&quot;/assets/2021-04-02-api-first-done-right/code-generation-spring.jpg&quot; alt=&quot;Code generation - Spring&quot; /&gt;

  &lt;figcaption&gt;
A model class generated using a customized model template (added Lombok support).
&lt;/figcaption&gt;
&lt;/figure&gt;

&lt;p&gt;Maven plugin configuration from the &lt;a href=&quot;https://github.com/piotrpolak/spring-boot-playground&quot;&gt;https://github.com/piotrpolak/spring-boot-playground&lt;/a&gt; prject.
Please note &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;configOptions&lt;/code&gt; for the &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;spring&lt;/code&gt; language:&lt;/p&gt;

&lt;div class=&quot;language-xml highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nt&quot;&gt;&amp;lt;plugin&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;groupId&amp;gt;&lt;/span&gt;org.openapitools&lt;span class=&quot;nt&quot;&gt;&amp;lt;/groupId&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;artifactId&amp;gt;&lt;/span&gt;openapi-generator-maven-plugin&lt;span class=&quot;nt&quot;&gt;&amp;lt;/artifactId&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;version&amp;gt;&lt;/span&gt;${openapi-generator-maven-plugin.version}&lt;span class=&quot;nt&quot;&gt;&amp;lt;/version&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;executions&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;execution&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;goals&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;goal&amp;gt;&lt;/span&gt;generate&lt;span class=&quot;nt&quot;&gt;&amp;lt;/goal&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/goals&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;configuration&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;inputSpec&amp;gt;&lt;/span&gt;${project.basedir}/src/main/resources/static/swagger.json&lt;span class=&quot;nt&quot;&gt;&amp;lt;/inputSpec&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;generatorName&amp;gt;&lt;/span&gt;spring&lt;span class=&quot;nt&quot;&gt;&amp;lt;/generatorName&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;output&amp;gt;&lt;/span&gt;${project.build.directory}/generated-sources/swagger&lt;span class=&quot;nt&quot;&gt;&amp;lt;/output&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;apiPackage&amp;gt;&lt;/span&gt;ro.polak.springbootplayground.api&lt;span class=&quot;nt&quot;&gt;&amp;lt;/apiPackage&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;modelPackage&amp;gt;&lt;/span&gt;ro.polak.springbootplayground.api.dto&lt;span class=&quot;nt&quot;&gt;&amp;lt;/modelPackage&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;invokerPackage&amp;gt;&lt;/span&gt;ro.polak.springbootplayground.api&lt;span class=&quot;nt&quot;&gt;&amp;lt;/invokerPackage&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;modelNameSuffix&amp;gt;&lt;/span&gt;Dto&lt;span class=&quot;nt&quot;&gt;&amp;lt;/modelNameSuffix&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;generateSupportingFiles&amp;gt;&lt;/span&gt;false&lt;span class=&quot;nt&quot;&gt;&amp;lt;/generateSupportingFiles&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;templateDirectory&amp;gt;&lt;/span&gt;${project.basedir}/templates/JavaSpring&lt;span class=&quot;nt&quot;&gt;&amp;lt;/templateDirectory&amp;gt;&lt;/span&gt;

                &lt;span class=&quot;c&quot;&gt;&amp;lt;!-- More options at https://openapi-generator.tech/docs/generators/spring --&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;configOptions&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;dateLibrary&amp;gt;&lt;/span&gt;java8&lt;span class=&quot;nt&quot;&gt;&amp;lt;/dateLibrary&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;interfaceOnly&amp;gt;&lt;/span&gt;true&lt;span class=&quot;nt&quot;&gt;&amp;lt;/interfaceOnly&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;library&amp;gt;&lt;/span&gt;spring-mvc&lt;span class=&quot;nt&quot;&gt;&amp;lt;/library&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;performBeanValidation&amp;gt;&lt;/span&gt;true&lt;span class=&quot;nt&quot;&gt;&amp;lt;/performBeanValidation&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;skipDefaultInterface&amp;gt;&lt;/span&gt;true&lt;span class=&quot;nt&quot;&gt;&amp;lt;/skipDefaultInterface&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;useOptional&amp;gt;&lt;/span&gt;true&lt;span class=&quot;nt&quot;&gt;&amp;lt;/useOptional&amp;gt;&lt;/span&gt;
                    &lt;span class=&quot;nt&quot;&gt;&amp;lt;sourceFolder&amp;gt;&lt;/span&gt;src/gen/java/main&lt;span class=&quot;nt&quot;&gt;&amp;lt;/sourceFolder&amp;gt;&lt;/span&gt;
                &lt;span class=&quot;nt&quot;&gt;&amp;lt;/configOptions&amp;gt;&lt;/span&gt;
            &lt;span class=&quot;nt&quot;&gt;&amp;lt;/configuration&amp;gt;&lt;/span&gt;
        &lt;span class=&quot;nt&quot;&gt;&amp;lt;/execution&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;nt&quot;&gt;&amp;lt;/executions&amp;gt;&lt;/span&gt;
&lt;span class=&quot;nt&quot;&gt;&amp;lt;/plugin&amp;gt;&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;/div&gt;

&lt;h4 id=&quot;code-generation-shortcomings---spring-boot&quot;&gt;Code generation shortcomings - Spring Boot&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Explicit &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;ResponseType&lt;/code&gt; as controller return types&lt;/p&gt;

    &lt;p&gt;If you like your controllers to return value objects directly or using void methods together &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@ResponseStatus&lt;/code&gt;
annotation — you will have to get used to the new style.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;Lack of the support for the &lt;a href=&quot;https://docs.spring.io/spring-framework/docs/current/javadoc-api/org/springframework/web/method/support/HandlerMethodArgumentResolver.html&quot;&gt;ArgumentResolvers&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://beanvalidation.org/1.0/spec/&quot;&gt;JSR Bean validation&lt;/a&gt; rules are leaked into the contract details or need
to be added programmatically&lt;/li&gt;
  &lt;li&gt;Code formatting issues and unused package imports&lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Code spoiled with metadata &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;@Api*&lt;/code&gt; annotations belonging to Swagger 2.0 — these come from an
outdated &lt;a href=&quot;https://mvnrepository.com/artifact/io.swagger/swagger-core&quot;&gt;swagger-core&lt;/a&gt; dependency (no longer maintained since 2017).&lt;/p&gt;

    &lt;p&gt;These annotations are only relevant when you use &lt;a href=&quot;https://springfox.github.io/springfox/&quot;&gt;SpringFox&lt;/a&gt; (out-of-box SwaggerUI integration with application bootstrap
classpath scanning) but this is definitively useless when you already have a well-crafted
definition available at your hand.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;adding-jsr-validation&quot;&gt;Adding JSR validation&lt;/h4&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;Annotations in OpenAPI definition&lt;/p&gt;

    &lt;p&gt;The resulting code includes JSR annotations at the field and class levels, however this causes the validation details
to leak into the OpenAPI specification.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Adding validation rules programmatically&lt;/p&gt;

    &lt;p&gt;Hibernate validator allows adding validation rules to any object. The code is characterized by high verbosity and
limited type safe constructs.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h3 id=&quot;generating-client-sdk-for-backend-to-backend-communication---java&quot;&gt;Generating client SDK for backend-to-backend communication - Java&lt;/h3&gt;

&lt;p&gt;There are few generators available for client SDK in java, these are build around multiple &lt;abbr title=&quot;Hypertext Transfer Protocol&quot;&gt;HTTP&lt;/abbr&gt; libraries, such as:
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jersey&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;jersey2&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;feign&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;okhttp-gson&lt;/code&gt; (default), &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;retrofit2&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;resttemplate&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;webclient&lt;/code&gt;,
&lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;resteasy&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;vertx&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;google-api-client&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;rest-assured&lt;/code&gt;, &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;native&lt;/code&gt; (Java 11 only), &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;microprofile&lt;/code&gt;&lt;/p&gt;

&lt;h4 id=&quot;picking-the-right-generator-for-java-client-sdk&quot;&gt;Picking the right generator for Java client SDK&lt;/h4&gt;

&lt;p&gt;Rules for picking a generator:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;available project dependencies&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;Whenever possible, pick a generator that does not require any additional dependencies.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;ease of customization&lt;/strong&gt; of the underlying &lt;abbr title=&quot;Hypertext Transfer Protocol&quot;&gt;HTTP&lt;/abbr&gt; client&lt;/p&gt;

    &lt;p&gt;Based on your needs, pick a generator that uses a client that allows customizing the &lt;abbr title=&quot;Hypertext Transfer Protocol&quot;&gt;HTTP&lt;/abbr&gt; client options such as
timeouts, interceptors and response processors. Clients (with few exceptions) support injecting a preconfigured &lt;abbr title=&quot;Hypertext Transfer Protocol&quot;&gt;HTTP&lt;/abbr&gt; client externally.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;consistency with existing &lt;abbr title=&quot;Hypertext Transfer Protocol&quot;&gt;HTTP&lt;/abbr&gt; clients&lt;/strong&gt; and other SDK clients in the project&lt;/p&gt;

    &lt;p&gt;If your Spring project already uses preconfigured &lt;abbr title=&quot;Hypertext Transfer Protocol&quot;&gt;HTTP&lt;/abbr&gt; client such as &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;RestTemplate&lt;/code&gt; or &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;WebClient&lt;/code&gt; it is probably
worth reusing it and benefit from the preconfigured connection options and request interceptors.
There is a chance that the Spring Framework takes care of injecting/forwarding &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Correlation-Id&lt;/code&gt; and &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Authorization&lt;/code&gt; headers.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;If the generator (&lt;abbr title=&quot;Hypertext Transfer Protocol&quot;&gt;HTTP&lt;/abbr&gt; library) needs to be changed after it has already been used in code, the following challenges
need to be addressed:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;&lt;abbr title=&quot;Hypertext Transfer Protocol&quot;&gt;HTTP&lt;/abbr&gt; client configuration&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;&lt;abbr title=&quot;Hypertext Transfer Protocol&quot;&gt;HTTP&lt;/abbr&gt; client configuration and request interceptors are not portable across the different &lt;abbr title=&quot;Hypertext Transfer Protocol&quot;&gt;HTTP&lt;/abbr&gt; libraries.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;&lt;strong&gt;error handling&lt;/strong&gt;&lt;/p&gt;

    &lt;p&gt;Each generator (&lt;abbr title=&quot;Hypertext Transfer Protocol&quot;&gt;HTTP&lt;/abbr&gt; library) throws different runtime exceptions upon communication issues. You need to review your
error handlers an controller advices to make sure the new types of exceptions are handled properly.&lt;/p&gt;

    &lt;p&gt;If your code handles connection exception manually (sometimes found to capture &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;Resource Not Found&lt;/code&gt;), then you need
to review all manual exception handling.&lt;/p&gt;

    &lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;bookstoreApi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getBookById&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;123&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;ConnectionException&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// This code will have to be changed&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// TODO Capture 404 and rethrow the rest&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;k&quot;&gt;try&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;{&lt;/span&gt;
  &lt;span class=&quot;n&quot;&gt;bookstoreApi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getBookById&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;mi&quot;&gt;123&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;catch&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;nc&quot;&gt;FeignException&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;e&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;){&lt;/span&gt;
  &lt;span class=&quot;c1&quot;&gt;// Doing the same as above &lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;p class=&quot;notice--warn&quot;&gt;Ask yourself a question whether you actually need to capture the exception — in many cases those situations are
not recoverable and are globally logged as errors anyway.&lt;/p&gt;

&lt;h4 id=&quot;switching-from-one-http-library-to-another&quot;&gt;Switching from one &lt;abbr title=&quot;Hypertext Transfer Protocol&quot;&gt;HTTP&lt;/abbr&gt; library to another&lt;/h4&gt;

&lt;p&gt;When switching from one library to another, your client code should be fine as long as you don’t add any custom
exception handling. Unfortunately most of the clients throw different types of exceptions (Runtime).&lt;/p&gt;

&lt;h4 id=&quot;addingforwarding-custom-headers&quot;&gt;Adding/forwarding custom headers&lt;/h4&gt;

&lt;p&gt;Adding/forwarding custom headers can be obtained in two ways:&lt;/p&gt;

&lt;ul&gt;
  &lt;li&gt;Adding a default headers — this might be suitable for values that are constant over time and shared across all the
users — for  an API Key:
    &lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;n&quot;&gt;bookstoreApi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getClient&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;()&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;addDefaultHeader&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;API-KEY&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;globalConfig&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getApiKey&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;())&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;

    &lt;p class=&quot;notice--warning&quot;&gt;NOTE: calling &lt;code class=&quot;language-plaintext highlighter-rouge&quot;&gt;addDefaultHeader&lt;/code&gt; after the API client has been initialized will change the state of the shared client
and might cause concurrency/security issues.&lt;/p&gt;
  &lt;/li&gt;
  &lt;li&gt;
    &lt;p&gt;Adding headers dynamically — whenever the header values differ from invocation to invocation, the best way to add
additional headers is to use interceptor mechanism of the underlying libraries.&lt;/p&gt;

    &lt;div class=&quot;language-java highlighter-rouge&quot;&gt;&lt;div class=&quot;highlight&quot;&gt;&lt;pre class=&quot;highlight&quot;&gt;&lt;code&gt;&lt;span class=&quot;nc&quot;&gt;RestTemplate&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;restTemplate&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;RestTemplate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;();&lt;/span&gt;
&lt;span class=&quot;n&quot;&gt;restTemplate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;addInterceptrs&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;asList&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;
  &lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;response&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;)&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;-&amp;gt;&lt;/span&gt;
    &lt;span class=&quot;n&quot;&gt;request&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;.&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;getHeaders&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;().&lt;/span&gt;&lt;span class=&quot;na&quot;&gt;add&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;s&quot;&gt;&quot;Custom-Authorization-Header&quot;&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;,&lt;/span&gt; &lt;span class=&quot;err&quot;&gt;…&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;))&lt;/span&gt;
&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;span class=&quot;nc&quot;&gt;BookstoreApi&lt;/span&gt; &lt;span class=&quot;n&quot;&gt;bookstore&lt;/span&gt; &lt;span class=&quot;o&quot;&gt;=&lt;/span&gt; &lt;span class=&quot;k&quot;&gt;new&lt;/span&gt; &lt;span class=&quot;nc&quot;&gt;BookstoreApi&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;(&lt;/span&gt;&lt;span class=&quot;n&quot;&gt;restTemplate&lt;/span&gt;&lt;span class=&quot;o&quot;&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;    &lt;/div&gt;
    &lt;p class=&quot;notice--warning&quot;&gt;&lt;strong&gt;Warning&lt;/strong&gt;: your project might already configure the &lt;abbr title=&quot;Hypertext Transfer Protocol&quot;&gt;HTTP&lt;/abbr&gt; client bean with some default interceptors/forwarders — this is
common for adding Correlation-ID.&lt;/p&gt;
  &lt;/li&gt;
&lt;/ul&gt;

&lt;h4 id=&quot;customizing-the-code-templates&quot;&gt;Customizing the code templates&lt;/h4&gt;

&lt;p&gt;Having so many generator options (see possible options for &lt;a href=&quot;https://openapi-generator.tech/docs/generators/spring/&quot;&gt;Spring generator
only&lt;/a&gt;) implies that the default templates are generic to serve
everyone’s needs.&lt;/p&gt;

&lt;p&gt;Some code bloat of the shortcomings mentioned in the previous section can be addressed by &lt;strong&gt;copying and
customizing code generator templates into your project&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;The templates use Mustache as the engine and usually require
one-time customization action. More on templating can be found at &lt;a href=&quot;https://openapi-generator.tech/docs/templating&quot;&gt;https://openapi-generator.tech/docs/templating&lt;/a&gt;
Things that are not possible to be customized with the templates only can be customized by creating a custom generator
language (see &lt;a href=&quot;https://github.com/OpenAPITools/openapi-generator/blob/master/modules/openapi-generator/src/main/java/org/openapitools/codegen/languages/SpringCodegen.java&quot;&gt;SpringCodeGen.java&lt;/a&gt;
for reference).&lt;/p&gt;

&lt;h3 id=&quot;generating-client-sdks-for-front-end-to-backend-communication&quot;&gt;Generating client SDKs for front-end-to backend communication&lt;/h3&gt;

&lt;p&gt;Frontend SDK can either be generated during the backend component build (and released as a dedicated NPM package) or during
the frontend application build.&lt;/p&gt;

&lt;p&gt;The generated SDK, when combined with TypeScript, can help to spot an incompatible change in the API during build
process rather than during manual tests.&lt;/p&gt;

&lt;p&gt;The TypeScript SDKs can either be generated:&lt;/p&gt;
&lt;ul&gt;
  &lt;li&gt;using the NPM wrapper around the OpenAPI tools (mentioned earlier)
&lt;a href=&quot;https://www.npmjs.com/package/@openapitools/openapi-generator-cli&quot;&gt;openapi-generator-cli&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;using JavaScript native tool, for example &lt;a href=&quot;https://www.npmjs.com/package/@lsongzhi/openapi-typescript-codegen&quot;&gt;openapi-typescript-codegen&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Using a JavaScript native tool makes it possible to avoid the need of installing Java on the development and build machines.&lt;/p&gt;

&lt;p&gt;A list of alternative generator tools can be found at &lt;a href=&quot;https://openapi.tools/#sdk&quot;&gt;https://openapi.tools/#sdk&lt;/a&gt;.
Pick the best suiting tool based on your needs and FE team preferences.&lt;/p&gt;

&lt;h3 id=&quot;testing-using-the-generated-sdk&quot;&gt;Testing using the generated SDK&lt;/h3&gt;

&lt;p&gt;Integration tests can be written using the SDK to further enhance the API development process. When using this approach,
tests are written using an SDK that is kept outside a version control.&lt;/p&gt;

&lt;p class=&quot;notice--warning&quot;&gt;If the existing tests fail to compile against a freshly generated SDK it means the OpenAPI got a backward incompatible change.&lt;/p&gt;

&lt;p class=&quot;notice--warning&quot;&gt;Tests using SDKs should not replace the contract test suits as it is possible to have two compatible SDKs generated for
two slightly different contracts.&lt;/p&gt;

&lt;h3 id=&quot;importing-openapi-definition-in-postman&quot;&gt;Importing OpenAPI definition in Postman&lt;/h3&gt;

&lt;p&gt;A well written OpenAPI definition can easily be imported into Postman. With good request examples and definitions you
can try the happy flows with the minimum adjustments (this might be as simple as providing the correct Authorization
header values).&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2021-04-02-api-first-done-right/postman.jpg&quot; alt=&quot;Postman&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2021-04-02-api-first-done-right/postman2.jpg&quot; alt=&quot;Postman&quot; /&gt;&lt;/p&gt;

&lt;p&gt;&lt;img src=&quot;/assets/2021-04-02-api-first-done-right/postman3.jpg&quot; alt=&quot;Postman&quot; /&gt;&lt;/p&gt;

&lt;h3 id=&quot;mocking-your-api&quot;&gt;Mocking your API&lt;/h3&gt;

&lt;p&gt;With the use of dedicated packages you can transform your rich OpenAPI definition into a realistic mock that can be used
for the frontend application development, independently on the backend services development.&lt;/p&gt;

&lt;p&gt;See &lt;a href=&quot;https://www.npmjs.com/package/openapi-mock-express-middleware&quot;&gt;openapi-mock-express-middleware&lt;/a&gt; or &lt;a href=&quot;https://www.npmjs.com/package/open-api-mocker&quot;&gt;open-api-mocker&lt;/a&gt; for more details.&lt;/p&gt;

&lt;p&gt;A comprehensive comparison of the mocking servers can be found at &lt;a href=&quot;https://openapi.tools/#mock&quot;&gt;https://openapi.tools/#mock&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;best-practices-when-maintaining-sdk-friendly-openapi-contracts&quot;&gt;Best practices when maintaining SDK-friendly OpenAPI contracts&lt;/h2&gt;

&lt;p&gt;See &lt;a href=&quot;/2021/04/08/best-practices-when-maintaining-sdk-friendly-openapi-contracts.html&quot;&gt;Best practices when maintaining SDK-friendly OpenAPI contracts&lt;/a&gt;.&lt;/p&gt;

&lt;h2 id=&quot;additional-resources&quot;&gt;Additional resources&lt;/h2&gt;

&lt;ul&gt;
  &lt;li&gt;&lt;a href=&quot;https://openapi.tools/&quot;&gt;https://openapi.tools/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://swagger.io/resources/articles/adopting-an-api-first-approach/&quot;&gt;https://swagger.io/resources/articles/adopting-an-api-first-approach/&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/Swagger_(software)&quot;&gt;https://en.wikipedia.org/wiki/Swagger_(software)&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://medium.com/adobetech/three-principles-of-api-first-design-fa6666d9f694&quot;&gt;https://medium.com/adobetech/three-principles-of-api-first-design-fa6666d9f694&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://en.wikipedia.org/wiki/OpenAPI_Specification&quot;&gt;https://en.wikipedia.org/wiki/OpenAPI_Specification&lt;/a&gt;&lt;/li&gt;
  &lt;li&gt;&lt;a href=&quot;https://medium.com/better-practices/api-first-software-development-for-modern-organizations-fdbfba9a66d3&quot;&gt;https://medium.com/better-practices/api-first-software-development-for-modern-organizations-fdbfba9a66d3&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;</content><author><name>Piotr Polak</name></author><summary type="html">This document is written from a Java/Fullstack developer perspective and it is intended to explain API First approach from the business, consumer, and API creator points of view.</summary></entry></feed>