Contract-first REST API

Heart of the application

Frontend

APIs

Code-first

Backend team code something

Generate documentation at runtime

Quicker, easier, more seductive

What does API-First mean?

API-first software development refers to a set of practices that formally recognize APIs as a first-class artefact of software development, and emphasize their strategic and architectural importance.

— Restlet

Contract first

Start with a contract

Everyone can mock from it

Contract can easily be versioned

Choose your weapon

editors

My little contract

openapi: 3.0.1
info:
  contact: {}
  description: Friendship is magic
  title: My Little Pony
  version: 1.0.0
servers:
- url: /
paths:
  /ponies:
    get:
      operationId: list
      parameters:
      - example: Rainbow Dash
        explode: true
        in: query
        name: name
        required: false
        schema:
          type: string
        style: form
      responses:

And now?

DRY - Generate

openapi generator
fork
stats

DEMO !

keyboard

First generation

npx openapi-generator generate -i .\api.yml -g spring -o ./spring

Api first generation

npx openapi-generator generate -i .\api.yml -g spring -p apiFirst=true -o ./spring-api

Plugin tweak

<plugin>
    <groupId>org.openapitools</groupId>
    <artifactId>openapi-generator-maven-plugin</artifactId>
    <version>4.2.2</version>
    <executions>
        <execution>
            <goals>
                <goal>generate</goal>
            </goals>
            <configuration>
                <inputSpec>src/main/resources/openapi.yaml</inputSpec>
                <generatorName>spring</generatorName>
                <apiPackage>org.openapitools.api</apiPackage>
                <modelPackage>org.openapitools.model</modelPackage>
                <generateSupportingFiles>false</generateSupportingFiles>
                <configOptions>
                    <interfaceOnly>true</interfaceOnly>
                    <delegatePattern>true</delegatePattern>
                </configOptions>
            </configuration>
        </execution>
    </executions>
</plugin>

Client

npx openapi-generator generate -i .\api.yml -g java --library=feign -o ./client

DefaultApi apiClient = new ApiClient()
        .setBasePath("http://localhost:8080")
        .buildClient(DefaultApi.class);

Pony pony = apiClient.getOne("id");
System.out.println("pony = " + pony);

Doc ?

npx openapi-generator generate -i .\api.yml -g asciidoc -o ./asciidoc

Just a demo

  • Plugin gradle and SBT (test)

  • Java, Scala, Kotlin♥, Go…​

  • Springboot, Ktor, Resttemplate..

Generated DTO vs Domain

Skip model generation and code them

Generated DTO vs Domain

Use mapper like mapstruct

Do I need that?

Mission Critical APIs.

When your API’s target audience are external customers

Questions

Thanks

Source code and slide can be found on https://github.com/Zomzog/contract-first