API-First Design Using MuleSoft’s Anypoint Platform
This article deals with defining your APIs using RAML, publishing to CloudHub, and sharing the API with developers so that they can play with it.
In this article, we work with five aspects of API-first development:
- Defining the API using RAML.
- Generating an application using RAML.
- Deploy the application in CloudHub.
- Sharing the deployed service through the developer portal.
- Accessing the developer portal.
Defining the API Using RAML
Anypoint Platform is owned by MuleSoft. Using Anypoint Platform, you can develop a full cycle of API applications. MuleSoft has its own runtime engine and has a lot of connectors (called Anypoint connectors), which are useful for quickly connecting to databases, transports, and other vendor-specific applications with a few steps.
MuleSoft has a very good reputation in the world of enterprise integration tools. MuleSoft is backed up by a huge developer community and it has community editions of software available for just getting your hands dirty. RAML is open-specification and the initiative has been taken by MuleSoft. MuleSoft has built their software with software patterns taken from Enterprise Integration Patterns by Gregory Hohpe and Bobby Woolf.
With RAML, you can follow the API-first development approach — you can design and test your API first and then develop the service later.
Let’s start designing the RAML file first. RAML stands for RESTful API Modeling Language. Using RAML, you can define your service’s APIs, build an application using Anypoint Studio, and share the API with the developer world.
I'm not going to explain how to build MuleSoft applications in this article but I will show you how to generate one using the RAML. You can define RAML using Anypoint Platform by registering for free or adding the package API Workbench to the Atom IDE. I have used Anypoint Platform to generate RAML. I have used Version 0.8 because I can generate a Swagger file from the RAML file to experiment using Azure API Management. I've found that most online converter tools only support RAML 0.8.
My RAML deals with designing APIs for an account service that has the following operations:
- Get Accounts (HTTP GET).
- Create a new Account (HTTP POST).
- Get Account for Account ID (HTTP GET).
- Delete an Account for Account ID (HTTP DELETE).
- Update an Account for Account ID (HTTP PUT).
The main advantage of using RESTful services is using HTTP methods for operations. The beauty is that it is light-weight and supports JSON and XML. REST is an architecture. Creating APIs (in our example) is just adhering to REST principles, but not whole gamut of REST.
Now, let's translate the operations to resource format and see how our APIs look before creating the actual.
Operation |
Resource URI |
HTTP Method |
Get Accounts |
/accounts |
GET |
Create a new Account |
/accounts |
POST |
Get Account for Account ID |
/accounts/{id} |
GET |
Delete an Account for Account ID |
/accounts/{id} |
DELETE |
Update an Account for Account ID |
/accounts/{id} |
PUT |
Now, we are ready, with the operations that we want to create an API for. Let's start by creating a RAML file for the above operations. I'm going to show my RAML text for you to understand. First, we need to specify RAML version and then the title of the service, the version of the service, and the base URI details as below:
#%RAML 0.8
title: Bank Accounts
version: v1
baseUri: http://accountsservice.cloudhub.io/api
Next, I will define my first operation (“Get Accounts”) as shown below:
/accounts:
description: Collection of Accounts
get:
description: Get list of all Accounts
responses:
"200":
description: Accounts found
body:
application/json:
example: |
[{
"id":"12345678",
"accountType":"Single",
"bankId":"BANK01",
"customerId":"CUST001"
},
{
"id":"910111213",
"accountType":"Single",
"bankId":"BANK01",
"customerId":"CUST002"
}]
"404":
description: No Accounts found
body:
application/json:
example: |
{
"message":"No Accounts found"
}
post:
description: Add an Account
body:
application/json:
example: |
{
"id":"910111214",
"accountType":"Single",
"bankId":"BANK01",
"customerId":"CUST003"
}
responses:
"201":
description: Account is successfully created
body:
application/json:
example: |
{
"id":"910111214",
"accountType":"Single",
"bankId":"BANK01",
"customerId":"CUST003"
}
As you can see, I can capture everything needed for the operation “Get Accounts.” I have defined the resource URI for the operation (/accounts) and specified the HTTP method that will be used to invoke the operation and sample responses for 200 and 404. I could mention the content type and description of each method. This is the beauty of defining RAML before actually coding. We can share the RAML file with the team members. They will get a clear picture about what to develop and it will be very easy to explain.
Similarly, my other operation design will be as below:
/{id}:
description: Particular Account
uriParameters:
id:
displayName: id
type: string
required: true
repeat: false
get:
description: Retrieve an account by id
responses:
"200":
description: Account by the specified account id exists.
body:
application/json:
example: |
{
"id":"12345678",
"accountType":"Single",
"bankId":"BANK01",
"customerId":"CUST001"
}
"404":
description: Account by the specified account id does not exists.
body:
application/json:
example: |
{
"message":"Account specified by the account id does not exists"
}
delete:
description: Delete an account by id
responses:
"204":
description: Successfully deleted the account specified by the id
body:
application/json:
example: |
{
"message":"Account specified by the id successfully deleted"
}
put:
description: Replace an account by id
body:
application/json:
example: |
{
"accountType":"Joint",
"bankId":"BANK01",
"customerId":"CUST001"
}
responses:
"204":
description: Successfully replaced the account details for the account id
body:
application/json:
example: |
{
"message":"Account specified by the id successfully updated"
}
documentation:
-
title: RAML for Accounts API
content: This is a sample RAML file for Bank Accounts API
When you go through the whole RAML file, you will understand the intention of the API and the operations supported. One more beautiful feature provided by Anypoint Platform is that you can start testing the operations without the actual service being deployed. Anypoint Platform dynamically generates mock services and you can test all your operations without consuming the actual service.
Just for reference, I will show you how it looks to test the RAML in the Anypoint Platform. I have logged into the Anypoint Platform, gone to API Manager, and opened my RAML file. If your RAML file is correctly formatted, then you should see on the right side of the page a section called Resources that has listed your resources with the supported operations. Also, you should see a Mocking Service slider on the top. You need to slide it to turn on the mocking service (you should see ON in green).
Figure 1: RAML with the mocking service.
I will not be testing all the operations, but I will test one to show how it works. When I click Post underneath the resource /accounts, I should see the description, security schemes, and body with examples if I have added an example for each operation. In our case, I have added them, so you should see examples of each operation. When you click Try it, you should see something like this on the right side of the screen:
Figure 2: The "try it" option.
When I click Try it, by default, the API Manager comments the original base URI and appends the mock service URI (https://mocksvc.mulesoft.com/…) as below:
Figure 3: Mock service appended in the RAML.
When I click Post, it submits the request to the mock service using the example request added in the RAML and responds back with the example response below:
Figure 4: Mock service request.
Figure 5: Mock service response.
Similarly, you can test all your operations without building the actual service to do any necessary changes.
As mentioned earlier, this helps you design and test your APIs before the actual development.
I would encourage to play with the creation of RAML using Anypoint Platform to understand what I have explained up to here. RAML is my favorite format of capturing my API requirements and I find it easy to share my design with developers.
As a recap, here are the basic instructions:
Browse the Anypoint website and create an account.
Once you create your account, log into the website. Click API Manager.
You will be presented with a screen for API Administration. Click Add new API.
Fill the details of the API and click the Add button. You can still modify the details any time you want.
Now, your API will be created. Now go to the API Definition section and click Edit in API designer.
You can either paste the RAML I have provided or you can write one by hand that gives you more intuition into designing RAML.
One beautiful feature that I would like to mention here is that this editor provides IntelliSense, like a feature that you would find in Visual Studio if you are a Microsoft Programmer or any Eclipse-based IDE if you are a Java developer. The hints provided in the API designer will help you successfully create your RAML.
Whether you pasted the RAML or created it by hand, you should see the Documentation section with Resources created in the RAML, listed out with the operations in the RAML.
Enable the mocking service by clicking the slider to test the operations without hitting the actual endpoint.
Save your RAML.
As a side note, RAML tools for .NET are available in the Visual Studio marketplace. .NET developers can now easily integrate and consume APIs in their projects. The project is available on GitHub here.