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:

  1. Defining the API using RAML.
  2. Generating an application using RAML.
  3. Deploy the application in CloudHub.
  4. Sharing the deployed service through the developer portal.
  5. 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:

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).

Image title

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:

Image title

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:

Image title

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:

Image title

Figure 4: Mock service request.

Image title

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:

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.

 

 

 

 

Top