OpenAPI, Java en Typescript

OpenAPI specification is een gestandaardiseerde manier om REST interfaces te beschrijven. Deze specificatie vind zijn oorsprong in het project Swagger. In 2016 is dit project ondergebracht bij de Open API specification initiative. In veel code en tools zul je dus nog regelmatig verwijzingen naar Swagger tegenkomen. Inmiddels is versie 3.0.0 van de specificatie uit.

De specificatie die je definieert kun je vergelijken met een WSDL definitie voor een SOAP service. Je kunt definiëren welke methode beschikbaar zijn, welke parameters met type er in gaan en wat er terug komt. Een grafische editor voor de definitie kun je vinden op de swagger site

Java code

Een andere optie is om op basis van bijvoorbeeld Java code een definitie te genereren. Hiervoor kun je  de gebruikelijke Spring MVC annotaties gebruik. Hierbij kan gedacht worden aan: @Controller , @RequestMapping , @PathVariable , @RequestBody  en @RequestParam . Daarnaast zijn er nog extra annotaties te vinden in bijvoorbeeld de swagger annotation library.

Het is belangrijk om na te denken over de keuze tussen het genereren of vooral definiëren van de specificatie. Bij het genereren op basis van code is het noodzakelijk om een extra stap op te nemen in het build proces. Dit is noodzakelijk zodat de definitie gemaakt wordt. Ook kan het zijn dat er extra annotaties nodig zijn om alles vast te leggen.  Andersom kan je gebruik maken van de standaard generate-sources stap.

De definitie genereren tijdens het build process kan door middel van een unit test. In deze test initialiseer je het spring MVC framework met alle controllers. Daarna is het mogelijk om met behulp van de volgende code een specificatie te genereren.

String outputDir = System.getProperty("io.springfox.staticdocs.outputDir");
MvcResult mvcResult = this.mockMvc.perform( get( "/v2/api-docs")
                                  .accept( MediaType.APPLICATION_JSON))
                                  .andExpect(status().isOk())
                                  .andReturn();

MockHttpServletResponse response = mvcResult.getResponse();
String swaggerJson = response.getContentAsString();
Files.createDirectories( Paths.get( outputDir));
try (BufferedWriter writer = Files.newBufferedWriter( Paths.get( outputDir, "swagger.json"), StandardCharsets.UTF_8)){
    writer.write(swaggerJson);
}

Deze definitie kan opgepakt worden door de maven ‘openapi-generator-maven-plugin’ om een client te genereren in een taal en framework naar keuze. Een lijst met ondersteunde mogelijkheden vind je hier: https://github.com/OpenAPITools/openapi-generator.

Het onderstaande voorbeeld is voor een Angular 7 project:

<plugin>
  <groupId>org.openapitools</groupId>
  <artifactId>openapi-generator-maven-plugin</artifactId>
  <version>3.3.4</version>
  <executions>
    <execution>
      <phase>prepare-package</phase>
      <goals>
        <goal>generate</goal>
      </goals>
      <configuration>
        <inputSpec>${project.build.directory}/swagger.json</inputSpec>
        <language>typescript-angular</language>
        <configOptions>
          <ngVersion>7.0</ngVersion>
        </configOptions>
        <output>${project.build.directory}/generated-client</output>
      </configuration>
    </execution>
  </executions>
</plugin>

Dezelfde plugin kan je ook gebruiken voor het genereren van van de server stub om zo tot bijvoorbeeld een Spring implementatie te komen.

Het gebruik van de OpenAPI specificatie in het build process, voorkomt het maken van fouten in aanroepen tussen client en server. De compiler zal veel fouten al van te voren detecteren. Mits er gebruik gemaakt wordt van een type checking. Tevens is er al een compleet model van DTOs wat het schrijven van code reduceert.

Samenvatting:

Inhoud van blog