Quickstart OpenAPI With Ballerina
Let's explore what we can do with the open-source API format for describing and documenting (OpenAPI) specification by using the Ballerina programming language.
Join the DZone community and get the full member experience.
Join For FreeWhat Is an API?
An Application Programming Interface (API) defines the allowed interactions between two pieces of software. It consists of the list of possible methods to call (requests to make), their parameters, return values, any data format they require, and many more. Here we focus on remote APIs, where the interacting parties run on separate machines and communicate over a network. APIs provide information hiding, and they can be thought of as an unbreakable contract.
Having API defined through a definition file is beneficial as:
- It is both human and machine-readable specification and less prone to getting outdated.
- Tools can use the API description to generate boilerplate code (in any programming language) to build provider and consumer applications.
What Is OpenAPI
OpenAPI Specification (formerly known as Swagger Specification) is an open-source format for describing and documenting APIs. The latest version of OpenAPI is 3.0. OpenAPI definitions can be written in JSON or YAML.
Swagger vs. OpenAPI
Swagger used to consist of the specification and a large ecosystem of tools to implement the specification.
The easiest way to understand the difference is:
- OpenAPI = Specification
- Swagger = Tools for implementing the specification
The Swagger toolset includes a mix of open-source, free, and commercial tools, which can be used at different stages of the API lifecycle, including editor, UI, codegen, Parser, etc.
In 2015, SmartBear Software donated the Swagger specification to the Linux Foundation and renamed the specification to the OpenAPI Specification. The development of the specification is fostered by the OpenAPI Initiative, which involves more than 30 organizations from different areas of the tech world, including Microsoft, Google, IBM, and CapitalOne and Smartbear Software, etc.
Since the Swagger tools were developed by the team involved in creating the original Swagger Specification, the tools are often still viewed as synonymous with the spec. But the Swagger tools are not the only tools that are available for implementing the OpenAPI Specification.
Advantages of Using OpenAPI
- Design first approach and will lead to accurate service/client implementation
- Provides collaborative API development as they are formalized plain-text documents.
- Acts as a source of truth for API testing
- Can avoid errors which get when writing boilerplate code
- Save time
OpenAPI Document Structure
An OpenAPI document is a text file, commonly called openapi.json or openapi.yaml, representing a JSON object, in either JSON or YAML format.
The root object in any OpenAPI document is the OpenAPI Object. Only two of its fields are mandatory.
- openapi — version of the OAS
- info — general information about the API. The `title` and `version` fields are mandatory.
Additionally, at least one of the following fields is required:
- paths — API Endpoints (also called Operations or Routes) are called Paths in the OAS.
- components — store re-usable definitions that might appear in multiple places in your specification document
- webhooks -The incoming webhooks that MAY be received as part of this API and the API consumer MAY choose to implement.
The Paths Field
- API Endpoints are called Paths in the OAS and are represented by paths object.
- Paths must start with a forward slash / since they are directly appended to the server URL o construct the full endpoint URL.
- Every field in the Paths Object is a Path Item Object describing one API endpoint. The Path Item Object describes the HTTP operations that can be performed on a path with a separate Operation Object for each one.
A simple document structure (with some important fields only) is as follows:
openapi:
info:
title:
description:
version:
paths:
/weather:
get:
tags:
summary:
description:
operationId:
externalDocs:
parameters:
- name:
in:
description:
schema:
type:
responses:
200:
description:
content:
application/json:
schema:
title:
deprecated:
security:
servers:
requestBody:
callbacks:
OpenAPI With Ballerina
Now let’s explore what we can do with OpenAPI using Ballerina programming language.
Note: If Ballerina is not installed already, follow the instructions and install Ballerina. Refer to the following video for more details.
The sample code in this article is using the Ballerina Swan Lake Beta2 version.
Ballerina supports the following modes of operations:
OpenAPI to Ballerina
If you already have an OpenApi Specification(OAS)-3 document for your service(s), you can use that contract to generate a Ballerina source code.
- Client generation — Generates a Ballerina client endpoint for a provided OAS definition.
- Service generation — Generates a mock version of the Ballerina service for a provided OAS definition.
Ballerina to OpenAPI
This allows generating an OpenAPI Specification(OAS) v3 definition of a Ballerina service.
Validate Service Implementation Against OpenAPI
The Ballerina OpenAPI compiler plugin validates the implementation of service against the specified OpenAPI contract during the compile time.
OpenAPI to Ballerina — Client Generation Example
In this post, I will explore the OpenAPI to Ballerina Client Generation scenario further. I am going to use a part of the disease.sh OpenAPI spec to generate a ballerina client from that. You can find a large number of clients generated for Ballerina language based on OpenAPI in the ballerinax-openapi-connectors repo.
Step 1: Save the following OpenAPI specification in a .yaml file:
openapi: "3.0.0"
servers:
- url: https://disease.sh
info:
version: 3.0.0
title: Novel COVID-19 API - Disease.sh - An open API for disease-related statistics
description: >
This is a generated connector from [Novel COVID-19 API version 3.0.0](https://disease.sh/docs/) OpenAPI Specification.
Ballerina connector for COVID-19 provides easy access to latest COVID-19 related data across the world. Please refer to [API documentation](https://disease.sh) for more detail.
license:
name: GNU V3
url: 'https://github.com/disease-sh/API/blob/master/LICENSE'
x-display:
label: COVID-19
iconPath: "resources/covid19.svg"
x-init-description: |
The connector initialization doesn't require setting the API credentials.
tags:
- name: 'COVID-19: Worldometers'
description: '(COVID-19 data sourced from Worldometers, updated every 10 minutes)'
- name: 'COVID-19: Vaccine'
description: '(COVID-19 vaccine trial data from raps.org, updated every 24 hours)'
paths:
/v3/covid-19/all:
get:
tags:
- 'COVID-19: Worldometers'
operationId: getGlobalStatus
x-display:
label: "Global Status"
parameters:
- name: yesterday
description: Enter `true`(1) to receive data reported a day ago. Default is `false`(0)
in: query
schema:
type: string
x-display:
label: "Yesterday"
- name: twoDaysAgo
description: Enter `true`(1) to receive data reported two days ago. Default is `false`(0)
in: query
schema:
type: string
x-display:
label: "Two Days Ago"
- name: allowNull
in: query
schema:
type: string
description: 'By default, value is 0. Enter `1` to allow nulls to be returned'
x-display:
label: "Allow Null"
summary: 'Get global COVID-19 totals for today, yesterday and two days ago.'
responses:
'200':
description: Global COVID-19 status
content:
application/json:
schema:
$ref: '#/components/schemas/CovidAll'
components:
schemas:
CovidAll:
properties:
updated:
type: number
description: Last updated timestamp
cases:
type: number
description: Total cases
todayCases:
type: number
description: Today cases
deaths:
type: number
description: Total deaths
todayDeaths:
type: number
description: Today deaths
recovered:
type: number
description: Total recovered
todayRecovered:
type: number
description: Today recovered
active:
type: number
description: Active cases
critical:
type: number
description: Critical cases
casesPerOneMillion:
type: number
description: Cases per one million
deathsPerOneMillion:
type: number
description: Deaths per one million
tests:
type: number
description: Total number of COVID-19 tests administered
testsPerOneMillion:
type: number
description: COVID-19 tests for one million
population:
type: number
description: World population
oneCasePerPeople:
type: number
description: One case per people
oneDeathPerPeople:
type: number
description: One deaths per people
oneTestPerPeople:
type: number
description: One tests per people
activePerOneMillion:
type: number
description: Active cases per one million
recoveredPerOneMillion:
type: number
description: Recovered cases per one million
criticalPerOneMillion:
type: number
description: Critical cases per one million
affectedCountries:
type: number
description: Affected countries
description: COVID-19 global status
externalDocs:
description: Find out more about this API
url: 'https://github.com/disease-sh/API'
Step 2: Navigate to the location where the .yaml file exists and create a new Ballerina project to place the source code of the client using the below command.
bal new client
It will create a folder named client
with main.bal
and Ballerina.toml
file.
Step 3: Generate the client Ballerina code using the following command.
bal openapi -i openapi.yaml — mode client -o client
The definition of the Ballerina openapi
command is as follows.
bal openapi [-i | — input] <openapi-contract-file-path> [ — mode <mode-type>] [-o | — output] <output-location>
The output of the above command is:
Note: This is an experimental tool, which only supports a limited set of functionality. Client generated successfully. Following files were created. -- client.bal -- types.bal
It has created two new .bal
files within the project folder.
The type.bal
will contain the type definitions required for this code. The client.bal
will contain the client implementation.

Step 4: Implement the client invocation code. Add the following code into the main.bal
file:
Step 5: Compile and run the Ballerina client package using the following command.
bal run client
You will see the output as follows which includes the COVID data.
Compiling source anupama/client:0.1.0Running executableGlobal Covid Data: {"updated":1630222838676.0,"cases":216770017.0,"todayCases":57222.0,"deaths":4508264.0,"todayDeaths":1396.0,"recovered":193703680.0,"todayRecovered":66956.0,"active":18558073.0,"critical":113386.0,"casesPerOneMillion":27810.0,"deathsPerOneMillion":578.4,"tests":3289818793.0,"testsPerOneMillion":419267.69,"population":7846583141.0,"oneCasePerPeople":0,"oneDeathPerPeople":0,"oneTestPerPeople":0,"activePerOneMillion":2365.12,"recoveredPerOneMillion":24686.37,"criticalPerOneMillion":14.45,"affectedCountries":223.0}
Summary
In this post, we’ve looked at how we can generate a client using an OpenAPI definition file with Ballerina language. The Ballerina openapi
tool is still in the experimental stage. Especially the user experience and openAPI spec compliance related to OpenAPI to Ballerina service generation and Ballerina to OpenAPI will improve further in the upcoming releases.
Published at DZone with permission of Anupama Pathirage. See the original article here.
Opinions expressed by DZone contributors are their own.
Comments