Generation

API-First

API-First

by Talend

 

 

API-First

by Talend

by API Team

 

API-First

by Talend

by API Team

by me

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

Code-first

Quicker, easier, more seductive

Lib springfox-swagger2

Dev must work before others can

API-First

Start with a contract

Everyone can mock from the contract

Slower to evolve

How to

We need a tool for creating an API definition :

And now?

OpenAPI-generator

Demo

Server side

<plugin>
    <groupId>org.openapitools</groupId>
    <artifactId>openapi-generator-maven-plugin</artifactId>
    <version>3.3.4</version>
    <executions>
        ...
    </executions>
</plugin>
<executions>
    <execution>
        <goals>
            <goal>generate</goal>
        </goals>
        <configuration>
            ...
        </configuration>
    </execution>
</executions>
<configuration>
    <inputSpec>
        ${project.basedir}/src/main/resources/api.yml
    </inputSpec>
    <generatorName>spring</generatorName>
    <configOptions>
        <sourceFolder>src/gen/java/main</sourceFolder>
        <interfaceOnly>true</interfaceOnly>
    </configOptions>
    <modelPackage>bzh.zomzog.apifirst.domain</modelPackage>
    <apiPackage>bzh.zomzog.apifirst.api</apiPackage>
    <generateSupportingFiles>true</generateSupportingFiles>
</configuration>
@RestController
public class PoniesController implements PoniesApi {

    @Override
    public ResponseEntity<Pony> getOne(String ponyId) {
        Pony pony = new Pony();
        pony.setId( "1" );
        pony.setName( "Rainbow dash" );
        pony.setColor( Pony.ColorEnum.RAINBOW );
        return ResponseEntity.ok( pony );
    }
}

Client side

<configuration>
    <inputSpec>
        ${project.basedir}/src/main/resources/api.yml
    </inputSpec>
    <generatorName>java</generatorName>
    <library>feign</library>
    <configOptions>
        <sourceFolder>src/gen/java/main</sourceFolder>
    </configOptions>
    <modelPackage>bzh.zomzog.prez.apifirst.domain</modelPackage>
    <apiPackage>bzh.zomzog.prez.apifirst.client.api</apiPackage>
    <generateSupportingFiles>true</generateSupportingFiles>
</configuration>
ApiClient apiClient = new ApiClient();
apiClient.setBasePath("http://localhost:8080");
Pony one = apiClient.buildClient(DefaultApi.class).getOne("1");

Works with kotlin

Generation vs Domain

Spring solution

BeanUtils.copyProperties(newObject, oldObject);

Only simple mapping same name, same type

Mapstruct

Generate mapper implementation at compile-time (annotation-processor).

Can do transformation

Can map immutable, use builder

Can be extended

Demo

<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-jdk8</artifactId>
</dependency>
<dependency>
    <groupId>org.mapstruct</groupId>
    <artifactId>mapstruct-processor</artifactId>
    <scope>provided</scope>
</dependency>
@Data
public class MyPony {

    private long id;
    private String name;
    private String color;
    private LocalDateTime createdAt;
    private String hiddenField;
}
@Mapper
public abstract class MyPonyMapper {

    public abstract MyPony map(Pony pony);
}
public LocalDateTime map(Long l) {
    return LocalDateTime.ofEpochSecond(l, 0, ZoneOffset.UTC);
}
@Mapper(componentModel = "spring",
        injectionStrategy = InjectionStrategy.CONSTRUCTOR,
        uses = NativeMapper.class)
@Mapping(target = "id", ignore = true)
public abstract MyPony update(Pony pony, @MappingTarget MyPony myPony);
@Builder
@Data
public class MyPony {

To API-First and beyond !

toInfinity

Fix API specification

Springfox is less than perfect

Spring Pageable

Generics

Nicknames

One step at a time

Generate DTO and map them to your domain

Generate and replace API

TL;DR

Design API with a tools

Generate client and server from it

Use a mapper to your domain objects

Show love with your APIs

Questions

Thanks

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