MuleSoft— Week 2 — Building APIs

After we have designed the API in the week 1, we will build and test our APIs this week.

Contents

Go to Week 1

Week 2
 — Introduction
 — Anypoint Studio
 — Mule Application Building Block
 — Connecting to Database
 — Transforming Data
 — Create RESTful Interfaces
 — Create RESTful Interfaces from APIkit
 — Connecting Interfaces to Implementations

To to week 3

Introduction

Mule Application

Mule applications accept and process messages through a series of message processors plugged together in a flow.

A message is initiated by an event.

Mule applications are written primarily in XML with Java and Spring under the hood.

Mule applications can be created and tested with Anypoint Studio, available standalone and as Eclipse plug-in.

Mule applications are deployed to a Mule runtime.

Mule Runtime

Mule runtime is basically a JVM server that handle and manage multiple Mule and non-Mule applications.

Mule runtime has two editions:

  • EE = Enterprise Edition, more capabilities
  • CE = Community Edition, open-sourced

Mule runtimes can be download here.

Mule Flow

Here is how the Mule application flow look like.

Normal flow includes message source which trigger the flow and message processor.

Mule Message

Inside a flow, there is a construct called Mule Message which normally consists of 4 parts.

Anypoint Studio

Anypoint Studio is an Eclipse-based IDE.

Here is how the Anypoint Studio look like:

Anypoint Studio has a build-in Mule runtime.

You can test your endpoint using either browser, cURL, Postman. Or you can automatically test with MUnit.

Anypoint Studio can be downloaded from here.

Create a New Mule Project

Go to menu File → New → Mule Project.

Name your project apdev-american, keep default settings and click Finish.

Drag HTTP connector to the Canvas.

Click + to configure HTTP connector.

Accept the default settings and click OK. Your server will listen at the port 8081.

Fill in the Basic Settings and click Save.
Path: /flights
Allowed Methods: GET

Drag Set Payload from the Transformers palette group.

Input Flight info into Value and save.

Click Configuration XML to see its source code.

Running Mule Application

Right click on the canvas and choose Run project…

If the application is successfully started you will see the status DEPLOYED.

Testing Mule Application

Open Postman and try to send a GET request to http://localhost:8081/flights

Shutdown Mule Application

Click the stop button.

Mule Application Building Block

Message Source

Message source is normally the first building block to receive new message.

Message sources are usually Anypoint connector which provide connectivity to external resources e.g. databases, protocols, or APIs

Endpoint-based Connectors

Inbound endpoints serve as a message source.

Outbound connectors send information to external systems.

Operation-based Connectors

Connectors not based on a standard communication protocol.

Connector vs. Endpoint

Connector = Mule-specific connection to an external resources

Endpoint = Flow-level element that configured to receive or send messages from/to external resources.

Global Elements

Endpoint/connector configuration is encapsulated in a global element so you can reuse them.

HTTP connector

HTTP Listener connector (inbound) = Listen for requests and provide HTTP response. Default host is 0.0.0.0 (Listen on all active IP Addresses)

HTTP Request connector (outbound) = Sends HTTP request and receives the returned response.

Message Processors

  • Connectors = Connect to an external resource
  • Scopes = Wraps snippet of code
  • Components = Execute specific logic upon a message
  • Transformers = Modifies the value of part of a message
  • Filters = Limit processing of messages based on criteria
  • Flow control = Direct messages through different pathways
  • Error handling = Handle any error that occur

Connecting to Database

The database connector can connect to almost JDBC-complaint relational databases.

Out-of-the-box support for MySQL, Oracle , and Derby.

Other databases are supported by a generic database configuration.

Configure MySQL Database Connector

Go back to your Mule project and remove the Set Payload element.

Search for Database palette and drag to the process area.

Double click the element and click + to add connector configuration. Select MySQL and click OK.

Set the database parameters and click Add File.
Host = mudb.mulesoft-training.com
Port = 3306
User = mule
Password = mule
Database = training

Select file mysql-connector-java-5.0.8-bin.jar and you should see the green checkmark. Click Test Connection… and you should get message “Test connection successful.

Click OK to go back to the database settings. Set Operation to Select and input the following in the query. Click Save.

SELECT *
FROM american

Run and Test

Run the application and test it with Postman. You should see the returned data like this:

Don’t forget to stop your application after use.

Setup Derby Database Locally (Optional)

If you don’t want to use MuleSoft database on the internet, you can alternatively running database services on your local machine.

Start the service by using command java -jar mulesoft-training-services-1.3.0.jar

Drag the file derbyclient-10.12.1.1.jar to your project. Select Copy files and click OK.

Right click the added file and select Build PathAdd to Build Path. The jar file will be added to the Referenced Libraries.

Go to Global Elements → Create.

Search and select Derby Configuration and click OK.

In the next window, select Configure via spring-bean and click + button.

Search and select StandardDataSource. Click OK.

In Bean Subelements, click + and select Add Property.

Fill in the following:
Name: driverName
Value: org.apache.derby.jdbc.ClientDriver

Click Finish and add another one:
Name: url
Value: jdbc:derby://localhost:1527/memory:training

Click OK and Test Connection… to make sure it is working.

Double click the Database element and change the connector configuration to Derby.

Run the application and test it. You should see the same result.

Transforming Data

Anypoint platform provides a set of transformers to handle the most common data transformation.

To create complex transformation, you need to use either:

  • Chained transformers
  • Create a custom Java transformer
  • Using a script transformer
  • Using the DataMapper transformer — with graphical interface

DataWeave

DataWeave is a full-featured and fully native framework for transforming data on Anypoint platform.

  • DataWeave Data Tranformation Lanaguge — JSON-like
  • 5X faster
  • Integrated with Anypoint Studio and DataSense
  • Can be used for all cases, simple to complex
  • No longer need to use other transformers unless you need to use specific Java framework
Graphical mapping on the left, Codes on the right

Adding JSON Transformer

Drag Object to JSON to the canvas. Save your project.

Run and test. You will see the output in JSON format.

Comparing to the sample response in our RAML we defined in week 1, there are some slight differences.

Adding DataWeave

Remove the existing transformer and add Transform Message instead.

Click Define Metadata.

Click + Add and name american_flights_json and click Create type.

Select Type Json. And select Example. Click  and select file american-flights-example.json. You will see the data structure showing up. Hit Select.

Drag from the left to the right to map fields. You can drag CODE1 and CODE2 into the same output field and both fields are automatically concatenated. Click Preview and click the link.

Double click the Transform Message tab to maximize it. Input the data on the left and you will see the output reflects on the right.

%dw 1.0
%output application/java
---
[{
AIRLINENAME: "American",
CODE1: "abc",
CODE2: "1234",
FROMAIRPORT: "LAX",
ID: 1,
PLANETYPE: "747",
PRICE: 1,
SEATSAVAILABLE: 1,
TAKEOFFDATE: |2003-10-01|,
TOAIRPORT: "CLE",
TOTALSEATS: 1
},
{
AIRLINENAME: "American",
CODE1: "abc",
CODE2: "1234",
FROMAIRPORT: "LAX",
ID: 1,
PLANETYPE: "747",
PRICE: 1,
SEATSAVAILABLE: 1,
TAKEOFFDATE: |2003-10-01|,
TOAIRPORT: "CLE",
TOTALSEATS: 1
}]

Save, Run, and test. Now you get the output in the format that you want.

Create RESTful Interfaces

Let’s create a few endpoints:

  • GET: /flights
  • GET: /flights/{id}
  • POST: /flights

Create GET Interface

Copy the entire flow (using Ctrl+C and Ctlr+V) and rename them to the following:

Update the path of the 2nd flow to /flights/{id} .

Update the database query to include Mule expression:

SELECT *
FROM american
WHERE ID = #[message.inboundProperties.'http.uri.params'.id]

Run and test. You should now be able to specify Flight ID dynamically in the Uri.

Create Mocking POST Interface

Add a new HTTP Listener to create a new flow. Reuse the same configuration. Set the same path but with POST in Allowed Method.

Add Set Payload and set Value to {“message”:”Flight added (but not really!)”} .

Save and test. You should get the response as we set in the Set Payload.

Create RESTful Interfaces from APIkit

APIkit is an open-source toolkit that let you generate interfaces in Mule application from RAML file.

Configure Anypoint Platform

Right click at the project and select Anypoint Platform → Configure.

In Authentication, click Add and sign in to Anypoint Platform.

Create New Project with APIkit

Create new Mule Project “apdev-american-ws”. Select Add APIkit components and click … → Anypoint Platform…

Select American Flights API that you created in the week 1.

The flows are automatically created.

Note that on the right you will see API Sync tab where you can download and upload changes to/from Anypoint Platform when you make change to RAML on either end.

In the generated flow, our example data is used as response.

Once you run the application, the APIkit Console will show up so you can test your APIs.

Of course, you can test with Postman as well. But you need to change the Uri a bit to http://localhost:8081/api/flights

Connecting Interfaces to Implementations

Now, we going to reuse existing flow in the new project from the previous project.

Copy Flow

Copy the xml file from the previous project to the new project using Copy and Paste.

Now, you may notice an error in MySQL database configuration of missing driver.

Even the Derby is not working.

This is because the dependent libraries are added to the previous project but not in the new project.

Add the libraries by copy and paste again.

Now, if you test connection, it should be successful.

Close the previous project.

Rename the XML files.
american.xmlinterface.xml
apdev-american.xmlimplementation.xml

Wiring the Flows

Now, we are going to make the interface flows call the implementation flows.

Let’s remove the duplicated HTTP listeners from the implementation flows.

Remove the HTTP configuration.

Remove all HTTP Listeners.

You will get this:

Open the interface flows and replace the Set Payload with Flow Reference and assign the correct implementation flow.

Make sure you get this:

Save all and run it. Test with APIkit Console. The GET /flights/{ID} should work. 
*If not, make sure the ID is consistent between Uri and Query as it is case-sensitive. So ID is not equal to id.

However, GET /flights with query string code is not working yet. We will fix that later.

Tip1: You can go to referenced flow by selecting Go to referenced flow.

Tip2: You can change the query parameter to #[flowVars.ID].

SELECT *
FROM american
WHERE ID = #[flowVars.ID]

Go to week 3

Show your support

Clapping shows how much you appreciated Chairat Onyaem’s story.