Archives Wild Code School
Java

OpenAPI with Spring Boot and Java

Quête 41 sur 43

Introduction

La spécification OpenAPI (standard de description d'API REST) offre une façon de documenter des RESTful API (API qui suivent les principes REST, un style d'architecture pour les services web) à l'aide d'un fichier JSON ou YAML. Avec les outils Swagger (ensemble d'outils construits autour d'OpenAPI), c'est facile de créer une documentation interactive pour l'API. Tu peux aussi générer le code du client et du serveur à partir de la spécification de l'API dans plusieurs langages de programmation et, dernier point mais non des moindres, tout est fourni en 100% Open Source.

OpenAPI

À la fin de cette quête

✅ Tu sais spécifier ton API avec OpenAPI ✅ Tu sais générer du code à partir de l'API ✅ Tu comprends les différents outils fournis par Swagger


Prérequis

✅ Tu as un ordinateur avec un système d'exploitation Linux 64 bits ✅ Tu as installé un JDK (Java Development Kit, le kit de développement Java) version 11 ou supérieure ✅ Tu comprends comment fonctionne Spring Boot ✅ Tu as implémenté une RESTful API avec Spring Boot (sans Swagger)


OpenAPI trouve ses racines dans Swagger mais a changé de nom pour refléter le caractère ouvert du projet. Comme OpenAPI est encore souvent appelé Swagger, ça peut créer un peu de confusion. La différence principale, c'est qu'OpenAPI fournit la spécification tandis que tous les outils gardent le préfixe Swagger.

Tout ce qui concerne OpenAPI et Swagger est déjà très bien documenté sur les sites web d'OpenAPI et de Swagger.

↗
https://openapi.org.org

La spécification OpenAPI

openapi.org.org
↗
https://swagger.io

Les outils Swagger

swagger.io

Avec OpenAPI et Swagger, tout commence vraiment par un fichier qui spécifie la RESTful API. On va plonger directement dans un exemple pour comprendre la structure et le contenu de la spécification de l'API. Dans cet exemple, on va utiliser le format de fichier .yaml, même s'il serait possible d'utiliser le format JSON à la place. C'est une question de goût (même si .yaml semble être le format privilégié au moment où ces lignes sont écrites) et les fichiers .yaml sont plus petits.

L'en-tête

Tout document OpenAPI commence par une seule entrée qui donne l'information de version d'OpenAPI. Note que la spécification OpenAPI actuelle a un numéro de version majeure égal à 3. Cette quête ne couvre pas l'ancienne spécification OpenAPI (Swagger).

Les informations de tout fichier OpenAPI suivent directement la version d'OpenAPI. Elles fournissent quelques informations communes sur l'API comme un titre, la version de l'API documentée et une courte description. D'autres données, par exemple sur l'auteur de l'API, sont optionnelles.

yaml
openapi: "3.1.0"
info:
  title: Simple OpenAPI example
  version: 0.0.1
  description: A simple example for OpenAPI

Après l'en-tête vient une liste de serveurs. Dans notre exemple simple, on référence un seul serveur, ici localhost puisqu'on veut juste montrer comment OpenAPI et les outils Swagger fonctionnent.

Référence du serveur

yaml
servers:
  - url: http://localhost:5000
    description: Sample server for this API

Spécification de l'API

La spécification de l'API fournit des informations détaillées sur les chemins, sur les paramètres fournis et sur le résultat attendu lors d'un appel à l'endpoint (point d'accès, une URL précise exposée par l'API) REST. Pour commencer, notre RESTful API ne fournira qu'un seul endpoint qui ne supporte qu'une requête GET. Un seul paramètre, personId, est fourni comme paramètre de chemin et la spécification restreint ce paramètre à être un nombre.

yaml
paths:
  /persons/{personId}:
    get:
      operationId: personGet
      summary: Fetch one person by id
      description: Get the person data 
      parameters:
      - name: personId
        in: path
        required: true
        schema:
          type: number
          example: 4
      responses:
        '200':
          description: Person
          content:
            application/json:
              schema:
                type: object
                properties:
                  firstname:
                    type: string
                    description: Name of person
                    example: "Paul"
                  lastname:
                    type: string
                    description: Last name of person
                    example: "Paulson"
                  age:
                    type: number
                    description: The current age of the person
                    example: 42

Une requête GET correspondante vers cet endpoint ressemblerait à ça

curl -X "GET" https://localhost/persons/42

Le résultat de la requête est censé être un document JSON qui représente une seule personne, comme dans :

json
{
   "firstname": "Paul",
   "lastname": "Paulson",
   "age": 42
}

Le bon côté de l'utilisation d'OpenAPI pour spécifier une RESTful API, c'est l'indépendance vis-à-vis de n'importe quel langage de programmation. Aucun programmeur n'a besoin d'apprendre un second langage pour comprendre comment la RESTful API fonctionne, même si une bonne compréhension de la spécification OpenAPI est nécessaire.

Une fois la RESTful API spécifiée (peut-être avec le Swagger Editor), le générateur de code Swagger (codegen) peut être utilisé pour créer le code du client ou du serveur, ce qui fait gagner beaucoup de temps au programmeur. Le générateur de code est disponible uniquement sous forme de service RESTful lui-même. Une autre variante du générateur de code, disponible pour les projets Java, est un plugin maven.

xml
<build>
    <plugins>
	<plugin>
	    <groupId>org.openapitools</groupId>
	    <artifactId>openapi-generator-maven-plugin</artifactId>
	    <version>5.2.0</version>
	    <executions>
		<execution>
		    <goals>
			<goal>generate</goal>
		    </goals>
		    <configuration>
			<inputSpec>${project.basedir}/src/main/resources/api.yaml</inputSpec>
		        <generatorName>spring</generatorName>
			<configOptions>
			</configOptions>
		    </configuration>
		</execution>
	    </executions>
	</plugin>
    </plugins>
</build>

L'extrait de pom.xml donné en exemple n'est pas complet, car on fournit d'habitude plus de détails dans la section de configuration pour affiner la façon dont le code est généré. Swagger codegen appliquera des valeurs par défaut si on ne fournit pas de configuration supplémentaire.

Le générateur propose plusieurs variantes. Dans ce cas, le code généré fonctionnera bien avec les projets Spring (Boot) puisqu'on a spécifié le nom de générateur correspondant. C'est une configuration obligatoire qui a du sens, puisque tu ne voudras jamais générer du code pour tous les frameworks et langages de programmation dans un seul projet.

Inclure les dépendances d'exécution de Swagger

Le code généré ajoute quelques dépendances. Pour que le code généré fonctionne, on doit inclure les bibliothèques qui contiennent ce code, comme on doit inclure les dépendances de tout autre code qu'on utilise dans notre projet. La différence, c'est que cette fois on n'a pas écrit le code nous-mêmes mais qu'on a laissé cette tâche à Swagger codegen.

xml
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>
<dependency>
   <groupId>io.swagger.core.v3</groupId>
   <artifactId>swagger-jaxrs2</artifactId>
   <version>2.1.10</version>
</dependency>
		
<dependency>
   <groupId>org.openapitools</groupId>
   <artifactId>jackson-databind-nullable</artifactId>
   <version>0.2.1</version>
</dependency>

Garde en tête que les choses peuvent changer quand une nouvelle version des outils Swagger est distribuée. Le code de cette quête est testé avec la version 2.9.2 de springfox-swagger2, même si une distribution plus récente est déjà disponible.

Inclure le Swagger-UI

Une fois le code généré, compilé et construit comme on le fait avec Spring Boot seul, l'application web est déjà utilisable même si le code généré fournit une implémentation par défaut. L'implémentation par défaut n'inclut aucune logique métier mais le code est complet.

Pour fournir des informations sur la RESTful API depuis l'application web, inclus la dépendance pour swagger-ui et tout est fait. Recompile et construis l'application et la documentation est disponible au chemin /swagger-ui.html.

xml
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>
		

Juste en incluant cette dépendance, Swagger fournira une UI qui propose une documentation interactive pour la RESTful API. Comme la documentation est interactive, tu peux l'essayer directement depuis le site web de documentation disponible sur ton serveur à /swagger-ui.html.

☝️ Résumé

La spécification OpenAPI et les outils Swagger offrent une façon indépendante du langage de spécifier une RESTful API. Avec l'aide du générateur de code Swagger, pas besoin de programmer quoi que ce soit pour l'UI, la seule tâche qui reste se situe au niveau métier, en général implémentée dans des services. Le Swagger-UI fournit une documentation interactive simplement en incluant la dépendance. L'intégration dans le Spring Framework te laisse un peu de configuration et t'évite d'avoir à coder réellement.

💪Challenge

Fournis ta propre RESTful API qui supporte au moins une requête GET et une requête POST. Tu dois

  • Utiliser le Swagger-Editor pour créer la spécification de l'API
  • Utiliser le Swagger-Codegen pour générer le code Java
  • Inclure le Swagger-Ui pour fournir des informations sur ton API

🧐 Critères d'acceptation

  • ⭙ Ton API fonctionne sur ton serveur
  • ⭙ Tu peux essayer l'API avec le Swagger-UI

Ne te soucie pas du contenu de ton API pour cette quête. Pas besoin d'utiliser une base de données. Tu peux simplement renvoyer des données statiques ou tout garder en mémoire.

Introduction

The OpenAPI specification provides a way to document RESTful API's using a JSON or YAML file. Using the Swagger tools it is easy to create an interactive documentation for the API. You can also generate code for the client and server from the API specification in several programming languages and last but not least, everything is provided as 100% Open Source.

OpenAPI

By the end of this quest

✅ Know how to specify your API using the OpenAPI ✅ Know how to generate code from the API ✅ Understand the different tools provided by Swagger


Prerequisites

✅ You have a computer with a 64 bit Linux operating system ✅ You have installed a Java JDK version 11 or above ✅ You understand how Spring Boot works ✅ You have implemented a RESTful API with Spring Boot (without Swagger)


The OpenAPI has its roots in Swagger but changed the name to reflect the openess of the project. Since OpenAPI is often still referred to as Swagger, this may cause a little bit of confusion. The main difference is that OpenAPI provides the specification while all tools stay with the Swagger prefix.

Everything about OpenAPI and Swagger is already very well documented on the websites for OpenAPI and Swagger.

↗
https://openapi.org.org

The OpenAPI specification

openapi.org.org
↗
https://swagger.io

The Swagger tools

swagger.io

With OpenAPI and Swagger, everything really starts with a file that specifies the RESTful API. We will dive directly into an example to understand the structure and content of the API specification. In this example, we will use the .yaml file format though it would be possible to use the JSON file format instead. It's a matter of taste (though .yaml seems to be the format of choice at the time of writing) and the .yaml files are smaller.

The header

Any OpenAPI document starts with a single entry that provides the OpenAPI version information. Note that the current OpenAPI specification has a major version number of 3. This Quest does not cover the older OpenAPI (Swagger) specification.

The information are of any OpenAPI file follows directly to the OpenAPI version. It provides some common information about the API like a title, the version of the documented API and a short description. Other data, for example about the author of the API, is optional.

yaml
openapi: "3.1.0"
info:
  title: Simple OpenAPI example
  version: 0.0.1
  description: A simple example for OpenAPI

Following the header is a list of servers. In our simple example, we reference only a single server - in this case localhost since we only want to show how OpenAPI and the Swagger tools work.

Server reference

yaml
servers:
  - url: http://localhost:5000
    description: Sample server for this API

API specification

The API specification provides detailed path information, information about parameters provided and about the expected result from a call to the REST endpoint. For a start, our RESTful API will provide only a single end point that supports only a GET request. A single parameter, personId, is pvoided as a path parameter and the specification restricts this parameter to be a number.

yaml
paths:
  /persons/{personId}:
    get:
      operationId: personGet
      summary: Fetch one person by id
      description: Get the person data 
      parameters:
      - name: personId
        in: path
        required: true
        schema:
          type: number
          example: 4
      responses:
        '200':
          description: Person
          content:
            application/json:
              schema:
                type: object
                properties:
                  firstname:
                    type: string
                    description: Name of person
                    example: "Paul"
                  lastname:
                    type: string
                    description: Last name of person
                    example: "Paulson"
                  age:
                    type: number
                    description: The current age of the person
                    example: 42

A corresponding GET request to this endpoint would be

curl -X "GET" https://localhost/persons/42

The result of the request is expected to be a JSON document that reflects a single person as in:

json
{
   "firstname": "Paul",
   "lastname": "Paulson",
   "age": 42
}

The good part about using OpenAPI to specify a RESTful API is the independance from any single programming language. No programmer has to learn a second language to understand how the RESTful API works, though a good understanding of the OpenAPI specification is required.

Once the RESTful API is specified - maybe using the Swagger Editor, the Swagger code generator (codegen) can be used to create the code for either the client or the server saving a lot of time for the programmer. The code generator is available only as a RESTful service itself. Another flavour of the code generator that is available for Java projects is a maven plugin.

xml
<build>
    <plugins>
	<plugin>
	    <groupId>org.openapitools</groupId>
	    <artifactId>openapi-generator-maven-plugin</artifactId>
	    <version>5.2.0</version>
	    <executions>
		<execution>
		    <goals>
			<goal>generate</goal>
		    </goals>
		    <configuration>
			<inputSpec>${project.basedir}/src/main/resources/api.yaml</inputSpec>
		        <generatorName>spring</generatorName>
			<configOptions>
			</configOptions>
		    </configuration>
		</execution>
	    </executions>
	</plugin>
    </plugins>
</build>

The example pom.xml snippet is not complete, since we usually provide more details in the configuration section to fine tune how code is generated. Swagger codegen will apply some defaults if we do not provide any further configuration.

The generator provides several flavours. In this case, the generated code will work well with Spring (Boot) projects as we specified the corresponding generator name. This is a required configuration that makes sense since you will never want to generate code for all frameworks and programming languages in a single project.

Include the Swagger runtime dependencies

The generated code add some dependencies. For the generated code to work, we have to include the libraries that include this code like we have to include the dependencies for any other code that we use in our project. The difference is that we did not write the code ourselve this time but we left this task to Swagger codegen.

xml
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger2</artifactId>
    <version>2.9.2</version>
</dependency>
<dependency>
   <groupId>io.swagger.core.v3</groupId>
   <artifactId>swagger-jaxrs2</artifactId>
   <version>2.1.10</version>
</dependency>
		
<dependency>
   <groupId>org.openapitools</groupId>
   <artifactId>jackson-databind-nullable</artifactId>
   <version>0.2.1</version>
</dependency>

Please keep in mind that things may change when a new version of the Swagger tools are distributed. The code in this quest is tested with Version 2.9.2 of springfox-swagger2 even though a newer distribution is already available.

Include the Swagger-UI

Once the code is generated, compiled and build like it is done with Spring Boot alone, the Web application is already usable though the generated code provides a default implementation. The default implementation does not include any business logic but the code is complete.

To provide information about the RESTful API from the web application, include the dependency for swagger-ui and everything is done. Recompile and build the application and the documenation is available at the /swagger-ui.html path.

xml
<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-swagger-ui</artifactId>
    <version>2.9.2</version>
</dependency>
		

Just by including this dependency, Swagger will provide a UI that provides an interactive documentation for the RESTful API. Since the documentation is interactive, you can try it out directly from the documentation website available on your server at /swagger-ui.html.

☝️ Summary

The OpenAPI specification and the Swagger tools provide a language agnostic way to specify a RESTful API. With the help of the Swagger code generator, there is no need to do any programming for the UI - the task left is on the business level usually implemented in some services. The Swagger-UI provides an interctive documentation by simply including the dependency. The integration into the Spring Framework leaves you with some configuration and frees you from actually coding.

💪Challenge

Provide your own RESTful API that supports at least one GET request and one POST request. You should

  • Use the Swagger-Editor to create the API specification
  • Use the Swagger-Codegen to generate the Java code
  • Include the Swagger-Ui to provide information about your API

🧐 Acceptance criteria

  • ⭙ Your API is working on your server
  • ⭙ You can try the API with the Swagger-UI

Do not care about the content of your API for this quest. There is no need to use a database. You may simply return some static data or keep everything in memory.