MuleSoft— Week 2 — Building APIs

Chairat Onyaem
Jun 28, 2017 · 12 min read
Image for post
Image for post

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.

Image for post
Image for post

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.

Image for post
Image for post

Anypoint Studio

Anypoint Studio is an Eclipse-based IDE.

Here is how the Anypoint Studio look like:

Image for post
Image for post

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.

Image for post
Image for post

Drag HTTP connector to the Canvas.

Image for post
Image for post

Click + to configure HTTP connector.

Image for post
Image for post

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

Image for post
Image for post

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

Image for post
Image for post

Drag Set Payload from the Transformers palette group.

Image for post
Image for post

Input Flight info into Value and save.

Image for post
Image for post

Click Configuration XML to see its source code.

Image for post
Image for post

Running Mule Application

Right click on the canvas and choose Run project…

Image for post
Image for post

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

Image for post
Image for post

Testing Mule Application

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

Image for post
Image for post

Shutdown Mule Application

Click the stop button.

Image for post
Image for post

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.

Image for post
Image for post

Operation-based Connectors

Connectors not based on a standard communication protocol.

Image for post
Image for post

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.

Image for post
Image for post

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.

Image for post
Image for post

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

Image for post
Image for post

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

Image for post
Image for post

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.

Image for post
Image for post

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
Image for post
Image for post

Run and Test

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

Image for post
Image for post

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.

Image for post
Image for post

Go to Global Elements → Create.

Image for post
Image for post

Search and select Derby Configuration and click OK.

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

Image for post
Image for post

Search and select StandardDataSource. Click OK.

Image for post
Image for post

In Bean Subelements, click + and select Add Property.

Image for post
Image for post

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

Image for post
Image for post

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.

Image for post
Image for post

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.

Image for post
Image for post

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
Image for post
Image for post
Graphical mapping on the left, Codes on the right

Adding JSON Transformer

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

Image for post
Image for post

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

Image for post
Image for post

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

Image for post
Image for post

Adding DataWeave

Remove the existing transformer and add Transform Message instead.

Image for post
Image for post

Click Define Metadata.

Image for post
Image for post

Click + Add and name american_flights_json and click Create type.

Image for post
Image for post

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

Image for post
Image for post

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.

Image for post
Image for post

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
}]
Image for post
Image for post

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

Image for post
Image for post

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:

Image for post
Image for post

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

Image for post
Image for post

Update the database query to include Mule expression:

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

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

Image for post
Image for post

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.

Image for post
Image for post

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

Image for post
Image for post

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

Image for post
Image for post

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.

Image for post
Image for post

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

Image for post
Image for post

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.

Image for post
Image for post

The flows are automatically created.

Image for post
Image for post

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.

Image for post
Image for post

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

Image for post
Image for post

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

Image for post
Image for post

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

Image for post
Image for post

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.

Image for post
Image for post

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

Image for post
Image for post

Even the Derby is not working.

Image for post
Image for post

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.

Image for post
Image for post

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

Close the previous project.

Image for post
Image for post

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.

Image for post
Image for post

Remove all HTTP Listeners.

Image for post
Image for post

You will get this:

Image for post
Image for post

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

Image for post
Image for post

Make sure you get this:

Image for post
Image for post

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.

Image for post
Image for post

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.

Image for post
Image for post

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

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

Go to week 3

Chairat.me

Personal blog of a developer who passionate in new…

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store