In the first part of this Swagger blog series, we learned about the history of the OpenAPI specification. In this article, we will:
- Explore Swagger’s enormous power to speed up your web application development using its code generator (https://github.com/swagger-api/swagger-codegen).
- Generate Code for a REST application using our own OpenAPI Specification file and swagger-codegen.
How Engineering Teams Should Develop Using Swagger?
There are two ways for developing using Swagger:
- API-First Approach (Top Down Approach):
First API Specification and then code generation. For this, you need to design your REST APIs first, then design model objects that you are going to use for those REST APIs. Then you write down these specifications in form of OpenAPI, and Swagger will create client as well as server for you! Sometime this approach also referred as API-Contract First approach.
- Service-First approach (Bottom Up Approach):
First API-Code and then code generation. As the name suggests, you write down your services (and REST controllers) first. Then you use swagger-core to automatically generate the Swagger definitions. Next you can use swagger-codegen and swagger-ui to generate client APIs and documentations.
In this article we only talk about Top-down or API-first approach of development using Swagger. (We will explore the other approach in the next part of this series.) For auto-generation of code using Swagger, the steps involved are:
- Write Swagger specification.
- Use swagger-codegen to generate client or server code.
Let’s look at these steps in more detail.
Writing Swagger Specification
As we have discussed in our last blog, Swagger uses OpenAPI specification that can be written in form of YAML or JSON. To understand this specification better, let’s take a very simple example of a Doctor Appointment Management application. We will be building a simple application with just two objects: Doctor, and Slot. And we will be generating client and server code with REST specifications as well as CRUD operations for Doctor and Slot objects, just by writing one single YAML file specification. To start writing a Swagger YAML file, you need to add info object at the start of YAML file.
swagger: "2.0" info: description: "Appointment Management" version: "1.0.0" title: "Doctor's Appointment" host: "localhost:8080" basePath: "/appointmentMgmt" schemes: - "http"
Important properties of this YAML file:
Property | Significance | Is Required? |
Swagger | Version of Swagger you want to use | Yes |
Host | The host (name or IP) serving the API. Optionally, you can add port as well. | No. If not provided, it uses the host and port serving the documentation. |
basePath | This is the context path for the hosted application | No. If not included, the API is served directly under the host |
Schemes | The transfer protocol of the API. Allowed Values are one of these: http, https, ws, wss | No |
Based on our host, schemes and basePath properties provided in above YAML, Swagger will generate REST API definitions in this format: Localhost:8080
Now let’s expand this YAML by writing our very first REST API definition. We will begin with the GET operation, as it is very straightforward.
paths: /doctors/{doctorId}: get: tags: - "Doctor" description: Get Doctos based on Id specified summary: Find Doctos by Id operationId: getDoctorsById produces: - "application/json" responses: 200: description: Doctor response schema: type: array items: $ref: '#/definitions/Doctor' 400: description: "Invalid Id supplied" 404: description: "Doctor not found" 405: description: "Validation exception" parameters: - name: doctorId in: path description: Id of Doctor to find required: true type: array items: type: string definitions: Doctor: type: "object" properties: doctorId: type: "integer" format: "int64" doctorName: type: "string" visitingCharge: type: "integer" format: "int64" availability: type: "integer" format: "int64" speciality: type: "string"
Let’s understand the important parts of this specification.
- paths: We have started writing YAML with paths object. It is specification for all paths and operations that you want to build inside your application.
- produces: A list of MIME types the operation can produce. The mime type definitions should be in compliance with RFC 6838.
- responses: We can specify all required/possible response types, and what should be returned by our REST API for each response type. Under response we have a schema.
- schema: A definition of the response structure. It can be a primitive, an array or an object. If it is an array, then it must be followed by items.
- items: Describes the type of items in the array.
- parameters: Used to define parameters that can be used across operations.
- in: It defines how the parameter is going to be passed. The possible values are "query”, "header", "path", "formData" or "body".
- required: To specify if parameter is mandatory.
- definitions: Object to hold data types produced and consumed by operations.
So basically, these are our model objects if we talk in terms of Java. In the above specification, we have defined one Doctor object, with 5 properties: doctorId, doctorName, visitingCharge, availability, and speciality.
Now that we have learnt basics of YAML, this YAML specification can be extended by writing more REST operations. This is our complete YAML specification file. Swagger provides its own editor to edit and compile YAML specification, as well as preview REST APIs that are generated out of your specification, in real time on your browser.
We will cover different options to set up Swagger editor in the next section.
Now that we are done with the YAML specification, let’s proceed with the second step to auto-generate code.
Swagger Code Generation
There are 3 ways to generate code from YAML specification.
Prerequisites
The following dependencies are required to be installed on the system before downloading and running the Swagger Codegen tool.
- Java – Version 7 or above.
- Using Swagger Editor:
- Swagger provides its own online editor (Swagger.io/ or Editor2.swagger.io ) where you can write specification in form of YAML or JSON.
- Alternatively, you can download code from GitHub (Github.com-swagger-api/swagger-editor) and run Swagger editor locally. After that, you can click on “Generate client” and select desired language. Or click on “Generate server” and select desired language. This will download all code required for client or server.
- Using command line tool swagger-codegen:
You can download Swagger jar from here
To generate client:
java -jar swagger-codegen-cli-2.2.2.jar
generate -i swagger.yml -l java -o SwaggerClient
To generate server:
java -jar swagger-codegen-cli-2.2.2.jar
generate -i swagger.yml -l
spring --library spring-mvc -o SwaggerServer
- -i: yaml file with location
- -l: language
- -o: output folder for generated source
(Note: There is also third-party component “swagger-js-codegen”, which can generate AngularJS or NodeJS source code from OpenAPI specification.)
- Using Maven plugin
You can also use swagger-codegen-maven-plugin within your existing maven project so that code generation can become part of your build life cycle.
The maven plugin example
<plugin> |
So, whenever you do mvn clean compile, the code will be automatically generated for you. Once your server code is generated, you can import it in our favourite IDE, and start up the server at the location specified in the host property of YAML.
Congratulations - you are now all set to develop your REST application and test it using Swagger-UI! This auto generated client and server code also generates .md files and provides nice documentation for your application’s REST endpoints. For our YAML specification, it has auto generated nice API endpoints summary for all the entities, as shown here.
You can have a look at this entire example project here.
In the next part of this series, we will explore other exciting features of Swagger. Stay tuned!