A Design-first approach to API implementation
Simplify your API Design, Development and Test using Oracle Apiary, OpenAPI and Swagger Tools
Each system should have a well-documented API to allow a structured and easy access to its functions and data. In this story, I want to explain how a top-down, design-first approach to implementing an API is possible, in order to combine agility with rigor. An approach that can be greatly simplified using Apiary.
Apiary is an acquisition that Oracle made some time ago, now integrated into the Oracle API Platform Cloud Service.
Using Apiary, you can design and specify an API interface using a YAML document that follows the OpenAPI specification (Swagger 2.0).
One first important thing to point out is that, if you write the interface using the Apiary editor, in real time is generated, based on specifications, comments and notes entered, a human-readable documentation, which is made accessible through the browser.
In this way, API designers can easily and quickly produce a well-crafted documentation, that is automatically kept in sync with the specs.
In Apiary two different formats for specification are supported: Blueprints, probably easier to use, and OpenAPI 2.0, that I’m going to use in the rest of this document (you will see soon why). Both are specifications for machine-readable files for describing, producing, consuming and visualizing a RESTFUL API.
If you want to start and try Apiary you can open a free account, even using your Github account.
A second important Apiary feature is that, as soon as you have developed a first version of the YAML spec file, you can save and synchronize this file in one of yours Github repositories. After, every changes made using Apiary editor can be saved in Github directly from inside Apiary.
If you want to have a look, you can see the repository I have created during the development of this story here. The example I have used is about an API developed for my Connected Car demo: it gives you the list of the cars registered and you can access to the list of trips and related informations (distance, diesel consumption and so on).
The documentation thus created can be immediately made available to developers who must consume this API, for example developers who are assigned the task of creating a Mobile Application, and they can start implementing the User Interface. This documentation becomes the contract between API developers and Mobile App developers.
But Apiary provides another tool that can greatly improve developers productivity: as soon as a first version of the API interface is available and published, Apiary implements a Mock Server, which developers can use to start testing the Mobile Application, or any others UI, even before the true implementation of the API is available.
The Mock Server is available at the URL specified in the top-left side of the Inspector initial screen:
If we invoke the various API endpoints using the Mock Server URL we can see all invocations in the Inspector screen and we can check if, for example, there are errors in the parameters or headers passed by the request.
In this example, a request has been submitted without a required header (Content-Type) and the error is clearly remarked.
Let’s move now to the implementation: if we have the definition of the API interface in OpenAPI (Swagger) 2.0 format, we can use the Swagger Tool swagger-codegen to generate a working skeleton, that can be used as a starting point to guide the implementation.
All the details for downloading and installing swagger-codegen can be found here.
The input for codegen is the YAML file we have created in Apiary. In my example, I have decided to implement the API using Python and the Flask framework. Here is the command that can be used to generate the entire skeleton:
swagger-codegen generate -i ./connectedcar2.yaml -l python-flask
From the help, you can see that a very large set of languages and frameworks is supported.
It is interesting to have a look at all the files generated:
All the instructions for using and changing the generated code are specified inside the README file. In requirements.txt you’ll find all the dependencies. But, what is really interesting is the fact that codegen has generated for us a Dockerfile that can be used to create an image and a container for start testing. This is the path I have decided to follow.
If you choose Python and Flask, as in my case, the code generated is based on the framework Connexion.
If we explore the code, down inside the swagger_server directory, we find a sub-directory containing the controllers and a sub-directory containing the generated models.
In default_controller.py each API endpoints is mapped to a distinct Python function; It is here that we must start working to implement our API, using the classes belonging to the model.
Obviously, we will need to add other Python modules to the already defined dependencies. For example, in my case I need to add the Python MySQL module, since my data are stored in a MySQL DB (the code to access DB is omitted…).
After we have developed the implementation and deployed in the Cloud, we can modify the YAML file inside Apiary, in order to point to the endpoint of the running API. At this time, we can change the settings in Apiary and switch it in PROXY mode. A different URL will appear in the Inspector screen and Apiary will act as a proxy between the client and the implementation. If we invoke the new exposed URL we can test again that requests and responses are compliant to the specs. On the contrary, the tool will highlight any difference, if any. Cool.
Apiary in addition can be used by itself to test the implementation and can generate the client code, for many different languages (or curl).
In my view, an API should be always implemented using a Design-first, top-down approach. But, since we want to follow an agile approach, with early feedbacks from our users, it is useful to provide them quickly documentation and a Mock Server to support their tests.
In this story, I have described how this approach can be realized using Apiary and OpenAPI.
For me, it has worked many times. Interesting to hear what you think.