The OpenAPI initiative aims at defining a standard for the specification of REST API. The OpenAPI Specification (OAS) defines a programming language-agnostic interface to describe a REST API. The Swagger Codegen generator supports more than 28 different languages (including Ada) and it is able to read an OpenAPI document and generate either the documentation or the client and server REST code for several target languages.
Generating a REST Ada client with OpenAPI and Swagger Codegen
By Stephane Carrez2017-10-08 18:32:00
Writing an OpenAPI document
The OpenAPI document is either a JSON or a YAML file that describes the REST API operations. The document can be used both for the documentation of the API and for the code generation in several programming language. We will see briefly through the Petstore example how the OpenAPI document is organized. The full OpenAPI document is available in petstore.yaml.
General description
A first part of the OpenAPI document provides a general description of the API. This includes the general description, the terms of service, the license and some contact information.
swagger: '2.0'
info:
description: 'This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://s
wagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key
` to test the authorization filters.'
version: 1.0.0
title: Swagger Petstore
termsOfService: 'http://swagger.io/terms/'
contact:
email: apiteam@swagger.io
license:
name: Apache 2.0
url: 'http://www.apache.org/licenses/LICENSE-2.0.html'
host: petstore.swagger.io
basePath: /v2
Type description
The OpenAPI document can also describe types which are used by the REST operations. These types provide a description of how the data is organized and passed through the API operations.
It is possible to describe almost all possible types from simple properties, group of properties up to complex types including arrays. For example a Pet
type is made of several properties each of them having a name, a type and other information to describe how the type is serialized.
definitions:
Pet:
title: a Pet
description: A pet for sale in the pet store
type: object
required:
- name
- photoUrls
properties:
id:
type: integer
format: int64
category:
$ref: '#/definitions/Category'
name:
type: string
example: doggie
photoUrls:
type: array
xml:
name: photoUrl
wrapped: true
items:
type: string
tags:
type: array
xml:
name: tag
wrapped: true
items:
$ref: '#/definitions/Tag'
status:
type: string
description: pet status in the store
enum:
- available
- pending
- sold
xml:
name: Pet
In this example, the Pet
type contains 6 properties (id
, category
, name
, photoUrls
, tags
, status
) and refers to two other types Category
and Tag
.
Operation description
Operations are introduced by the paths
object in the OpenAPI document. This section describes the possible paths that can be used by URL and the associated operation. Some operations receive their parameter within the path and this is represented by the {name}
notation.
The operation description indicates the HTTP method that is used get
, post
, put
or delete
.
The following definition describes the getPetById
operation.
paths:
'/pet/{petId}':
get:
tags:
- pet
summary: Find pet by ID
description: Returns a single pet
operationId: getPetById
produces:
- application/xml
- application/json
parameters:
- name: petId
in: path
description: ID of pet to return
required: true
type: integer
format: int64
responses:
'200':
description: successful operation
schema:
$ref: '#/definitions/Pet'
'400':
description: Invalid ID supplied
'404':
description: Pet not found
security:
- api_key: []
The summary
and description
are used for the documentation purposes. The operationId
is used by code generators to provide an operation name that a target programming language can use. The produces
section indicates the media types that are supported by the operation and which are generated for the response. The parameters
section represents all the operation parameters. Some parameters can be extracted from the path (which is the case for the petId
parameter) and some others can be passed as query parameter.
The responses
section describes the possible responses for the operation as well as the format used by the response. In this example, the operation returns an object described by the Pet
type.
Using Swagger Codegen
The documentation and the Ada client are generated from the OpenAPI document by using the Swagger Codegen generator. The generator is a Java program that is packaged within a jar file. It must be launched by the Java 7 or Java 8 runtime.
Generating the documentation
The HTML documentation is generated from the OpenAPI document by using the following command:
java -jar swagger-codegen-cli.jar generate -l html -i petstore.yaml -o doc
Generating the Ada client
To generate the Ada client, you will use the -l ada
option to use the Ada code generator. The OpenAPI document is passed with the -i
option.
java -jar swagger-codegen-cli.jar generate -l ada -i petstore.yaml -o client \
-DprojectName=Petstore --model-package Samples.Petstore
The Ada generator uses two options to control the generation. The -DprojectName=Petstore
option allows to control the name of the generated GNAT project and the --model-package
option controls the name of the Ada package for the generated code.
The Ada generator will create the following Ada packages:
Samples.Petstore.Models
is the package that contains all the types described in the OpenAPI document. Each OpenAPI type is represented by an Ada record and it
is also completed by an instantiation of the Ada.Containers.Vectors
package for the representation of arrays of the given type. The Models
package also provides Serialize
and Deserialize
procedures for the serialization and deserialization of the data over JSON or XML streams.
Samples.Petstore.Clients
is the package that declares theClient_Type
tagged record which provides all the operations for the OpenAPI document.
For the Pet
type describe previously, the Ada generator produces the following code extract:
package Samples.Petstore.Models is
...
type Pet_Type is
record
Id : Swagger.Long;
Category : Samples.Petstore.Models.Category_Type;
Name : Swagger.UString;
Photo_Urls : Swagger.UString_Vectors.Vector;
Tags : Samples.Petstore.Models.Tag_Type_Vectors.Vector;
Status : Swagger.UString;
end record;
...
end Samples.Petstore.Models;
and for the operation it generates the following code:
package Samples.Petstore.Clients is
...
type Client_Type is new Swagger.Clients.Client_Type with null record;
procedure Get_Pet_By_Id
(Client : in out Client_Type;
Pet_Id : in Swagger.Long;
Result : out Samples.Petstore.Models.Pet_Type);
...
end Samples.Petstore.Clients;
Using the REST Ada client
Initialization
The HTTP/REST support is provided by Ada Util and encapsulated by Swagger Ada. The Ada Util library also takes care of the JSON and XML serialization and deserialization. If you want to use Curl, you should initialize with the following:
with Util.Http.Clients.Curl;
...
Util.Http.Clients.Curl.Register;
But if you want to use AWS, you will initialize with:
with Util.Http.Clients.Web;
...
Util.Http.Clients.Web.Register;
After the initialization is done, you will declare a client instance to access the API operations:
with Samples.Petstore.Clients;
...
C : Samples.Petstore.Clients.Client_Type;
And you should initialize the server base URL you want to connect to. To use the live Swagger Petstore service you can set the server base URL as follows:
C.Set_Server ("http://petstore.swagger.io/v2");
At this stage, you can use the generated operation by calling operations on the client.
Calling a REST operation
Let's retrieve some pet information by calling the Get_Pet_By_Id
operation described previously. This operation needs an integer as input parameter and returns a Pet_Type
object that contains all the pet information. You will first declare the pet instance as follows:
with Samples.Petstore.Models;
...
Pet : Samples.Petstore.Models.Pet_Type;
And then call the Get_Pet_By_Id
operation:
C.Get_Pet_By_Id (768, Pet);
At this stage, you can access information from the Pet
instance:
with Ada.Text_IO;
...
Ada.Text_IO.Put_Line ("Id : " & Swagger.Long'Image (Pet.Id));
Ada.Text_IO.Put_Line ("Name : " & Swagger.To_String (Pet.Name));
Ada.Text_IO.Put_Line ("Status : " & Swagger.To_String (Pet.Status));
The Swagger Ada Petstore illustrates other uses of the generated operations. It allows to list the inventory, list the pets with a given status, add a pet and so on...
Conclusion and references
The OpenAPI Specification provides a standard way to describe REST operations. The Swagger Codegen is the generator to be used to simplify the implementation of REST clients in many programming languages and to generate the documentation of the API. The Ada code generator only supports the client side but the server code generation is under work.
The sources of the petstore samples are available:
- petstore.adb
- samples-petstore-models.ads
- samples-petstore-models.adb
- samples-petstore-clients.ads
- samples-petstore-clients.adb
The APIs.guru lists more than 550 API descriptions from various providers such as Amazon, Google, Microsoft and many other online services. They are now available to the Ada community!
Tags
- Facelet
- NetBSD
- framework
- Mysql
- generator
- files
- application
- gcc
- ReadyNAS
- Security
- binutils
- ELF
- JSF
- Java
- bacula
- Tutorial
- Apache
- COFF
- collaboration
- planning
- project
- upgrade
- AWA
- C
- EL
- J2EE
- UML
- php
- symfony
- Ethernet
- Ada
- FreeBSD
- Go
- KVM
- MDE
- Proxy
- STM32
- Servlet
- backup
- lvm
- multiprocessing
- web
- Bean
- Jenkins
- release
- OAuth
- ProjectBar
- REST
- Rewrite
- Sqlite
- Storage
- USB
- Ubuntu
- bison
- cache
- crash
- Linux
- firefox
- performance
- interview
Add a comment
To add a comment, you must be connected. Login