Anatomy of a MuleSoft API – The Bare Bones

As we start off another month of the COVID-19 quarantine, I confess I’m going a bit stir crazy. And so I decided it was time to write another blog post. After mulling things over for a while, I decided to tackle the subject of MuleSoft API development. Being a very broad topic with lots to write about, I had to ask myself where to begin. Should I write about API Design? Testing? Security? Deployment strategies? Monitoring? The possibilities were endless. I decided to start with the basics, which I plan to use as the foundation to build on in future blog posts.

And what do I mean by the basics exactly? I am referring to the bare bones minimum elements required to create something that can be referred to as a MuleSoft API, namely a specification and an implementation.

The Specification

The specification is really the key element that sets a MuleSoft API apart from any other type of MuleSoft application or integration. It defines the interface (the “I” in API) contract that the API will adhere to, essentially supplying the language that allows clients to talk to the API. It is important that the specification be developed before the implementation, in keeping with MuleSoft’s API-first design philosophy.

The Implementation

The implementation consists of the MuleSoft application that carries out the terms of the interface contract, so that when a client calls the API, it actually does the things specified in the contract.

The Bare Bones Solution

I decided to put together a simple proof of concept to demonstrate the makings of a bare bones solution, which I’ll discuss in detail below. The PoC uses Mule 4 and Anypoint Studio 7.4, so your mileage may vary if you’re using another version of Mule or Studio. Also, I’ve included links to the API specification that I used as well as the Anypoint Studio Project that was auto-generated by the API specification at the bottom of the post.

Designing The Specification 

A MuleSoft API specification can be created using one of two language formats: RESTful API Modeling Language (RAML), developed by MuleSoft, and OpenAPI Specification (OAS), formerly known as Swagger. MuleSoft’s Anypoint Studio, the tool we will need to use to develop our API implementation, only supports RAML. Therefore, be advised that any specification developed using OAS would first need to be converted to RAML before it can be used for creating the implementation. 

RAML and OAS API specifications can be created using any number of tools, including MuleSoft’s Anypoint Platform Design Center, SwaggerHub, or even something as simple as a text editor. You can also find a plethora of ready-made examples online.

If you used OAS to design your API specification, there are a number of ways to convert it to RAML. Two of the easiest ways would be to use the OAS RAML Converter or else to publish your OAS specification as a new asset of type “REST API – OAS” in MuleSoft’s Anypoint Platform Exchange and then download the asset as RAML. (MuleSoft will auto-convert it to RAML for you). Note that a valid API specification consists of one or more files that can be organized into a hierarchical folder structure. If your specification consists of multiple files, using Exchange to do the conversion might be preferred, as the OAS RAML Converter utility operates on a single file at a time.

I created the very basic “Hello World” RAML specification below for purposes of the proof of concept and saved it as a gist on Github. The RAML specifies an API with a single “/hello” endpoint and an example return message containing “Hello Mule API!”.

Creating The Implementation

Now we’re ready to create the implementation. For this we will need to use MuleSoft’s Anypoint Studio. The first step is to create a new project in Anypoint Studio by importing our API specification. There are multiple ways to import an API specification into an Anypoint Studio project. For my proof of concept, I chose to import my “Hello World” RAML specification from my local file system. 

As part of creating the new project, Anypoint Studio will build all of the basic API scaffolding for you automatically, including a console that can be used to view the specification, as well as to try out the API’s endpoints.  After importing my basic API RAML into Anypoint Studio, I had a working Mule application. Below is a screenshot of the Anypoint Studio project structure. You can see my API specification RAML file under /src/main/resources/api and the main Mule application file hello-mule-api.xml under /src/main/resources, the latter file being auto generated by Anypoint Studio when I created the new project.

The contents of the hello-mule-api.xml file forms the entirety of the API logic. The MuleSoft APIkit Plugin is responsible for creating the project scaffolding based on the provided API specification. The APIkit Plugin will by default generate a number of Mule application flows.

The first flow that will be created is the main flow, shown below, which is responsible for listening to all HTTP requests and then routing them to the appropriate flow based on the API specification. This flow also handles general HTTP exceptions, bad request, resource not found, etc. By default the main flow will listen for requests at the “/api” endpoint. So any calls to the API should be specified using the format “{api.url}/api/{specification.endpoint}”.

API Root Flow Listening at /api

The second flow that will be created is for the API Console, which listens at its own endpoint – “/console”. Navigating to “{api.url}/console/” in a web browser will display the API Console, which can be used to explore the API in a “human friendly” way. The API Console is also available when designing the API from Anypoint Platform’s Design Center.

API Console Flow Listening at /console

Here is a view of the API Console. I had some problems getting this to work. Initially it displayed as a blank screen, due to an incompatible version of the APIKit plugin that is installed into the project by default. Instructions on how to get around this issue are in the Reference Links section at the bottom of the post.

API Console running locally

Finally, one flow will be created for each of the endpoints defined in the API specification. In my case, I specified a single endpoint, so APIkit generated a total of three flows, shown below. Note that each of the flows created based on the API’s specification will not have their own HTTP Listener. The APIkit Router in the main flow is responsible for listening for all HTTP requests and then routing them to the appropriate flow based on the specification. Note also that APIkit automatically created a message transform based on the example defined for the /hello endpoint in my RAML specification. So I can build and deploy an actual “working” API just from the specification alone, which is pretty cool.

Flow for /hello Endpoint

So that’s it. You should now have a working API that can be deployed to any compatible MuleSoft deployment environment. In my next post, I will cover how to deploy this basic app to CloudHub using a CI/CD pipeline I put together using GitHub Actions. Stay safe!

Code Links

Reference Links

*Featured image courtesy of Mathew Schwartz at unsplash