What you'll do

  1. Create a Mule App using Anypoint Studio.
  2. Connect the app with a Redis instance and perform the basic methods.
  3. Interact with an existing database and modify the information using more advanced techniques.

What you'll learn

What you'll need

You'll need to download Docker for desktop.

Download Docker

From the terminal run this command:

$ docker run -p 6379:6379 --name some-redis -d redis

It will start a Redis instance locally with the name some-redis (you can choose any name). And the port will be 6379.

Here is up and running:

We are going to define an API.

1. Go to Design Center and create an API Spec.

The idea of the API is to implement the methods GET, POST and DELETE in the endpoint /redis in the simplest way possible.

2. Create the RAML file with its three methods.

#%RAML 1.0
title: Redis Lab API

mediaType:
- application/json

types:
 key-value: !include datatypes/key-value-object.raml

/redis:
 get:
   description: Get a value of the specified key.
   queryParameters:
     key:
       type: string
       description: The key matching the value we are looking for.
   responses:
     200:
       body:
         example: The value is one-value.
     404:
       body:
         example: Key not found.     
 post:
   description: Set the key to hold the payload (value). If the key already holds a value, it is overwritten.
   body:
     type: key-value
     examples:
         input: !include examples/key-value-example.raml
   responses:
     201:
       body:
         example: Successfully set value 'one-value' to key 'one-key'.
 delete:
   description: Delete the key and the value.
   queryParameters:
     key:
       description: The key matching the value we are looking for deleting.
   responses:
     200:
       body:
         example: The delete was successful.
     404:
       body:
         example: Key not found.

3. Create the type and example for using in the definition of the API.

Key-value-object:

#%RAML 1.0 DataType
type: object
properties:
 key: string
 value: any

Key-value-example:

#%RAML 1.0 NamedExample
value:
 key: "1"
 value: "first value"

4. We are going to use the Training API "American Flights" and we will get data from there. Using Redis as a cache. And using the endpoint /flight/{ID} to GET one flight by its ID.

Create the method in the Redis Lab API RAML:

/flight/{ID}:
 get:
   description: Get a flight of the specified ID.
   responses:
     200:
       body:
         example: !include examples/flight.json
     404:
       body:
         example: Flight not found.   

5. Create an example richer than the one that is given back from the Flights API.

{
 "ID": 1,
 "code": "GQ574",
 "price": 399,
 "departureDate": "2016/12/20",
 "origin": "ORD",
 "originDesc": "Orlando",
 "destination": "SFO",
 "destinationDesc": "San Francisco",
 "emptySeats": 200,
 "plane": {
   "type": "Boeing 747",
   "totalSeats": 400,
   "services": {
     "toilets": 8
   }
 }
}

6. Once it is all ready, publish the API to Exchange.

1. Create a new Mule Project and choose a project name.

2. In the section API Implementation, add your published API from Exchange.

3. The API will be added. Hit ‘finish' and you will be ready to start.

4. Add the Redis Connector to the Mule Palette

5. Create a file named config.yaml (in src/main/resources) to avoid hardcoded values in the Redis Connector. Use the values provided by Docker.

redis: 
  host: "localhost"
  port: "6379"
  connectionTimeout: "2000"

6. In the xml file automatically created (in my case named ‘redis-lab-api'), switch to Global Elements view and add a new configuration for the config.yaml.

Select from the Mule Palette the Get method from Redis and drag it to the flow:

Create a Redis Configuration and add a key attributes.queryParams.key :

Add a Set Payload and drag it to the flow:

Add a Display Name ‘See Value'. Then, in the Settings in the field Value write:

if (not isEmpty(payload)) "The value is: " ++ payload
else "The key was not found"

Select from the Mule Palette the Set method from Redis and drag it to the flow:

Add the Redis Configuration created in the Get method (in my case it is named ‘Redis_Redis_API').

In the field Key write payload.key.

In the field Value write write(payload.value, "application/json")

Go to the Advanced tab and add a Target Variable named ‘result' for not overwriting the payload.

Add a Set Payload and drag it to the flow:

Add a Display Name ‘See Value Response'. Then, in the Settings in the field Value write:

%dw 2.0
output text/plain
---
"Successfully set value: '" ++ write(payload.value, "application/json") ++ "' to key: '" ++ payload.key ++ "'"

Select from the Mule Palette the Del method from Redis and drag it to the flow:

Add the Redis Configuration.

In the field Key write attributes.queryParams.key.

We want to notify a subscriber every time a delete was successful.

We are going to use a Choice Router. If the delete was successful (payload = 1) we notify the subscriber, but if it was not successful (payload = 0) we only set the payload to "key not found".

Select from the Mule Palette the Choice Router and drag it to the flow:

In the When flow set the expression to payload == 1.

Add a Set Payload with Display Name ‘ Success Response ‘ and Value "The delete was successful".

Select from the Mule Palette the Publish method from Redis and drag it to the flow:

Add the Redis Configuration, name the channel ‘changes' and set the Message to "An element was deleted from the database".

In the Advanced tab add a Target Variable named ‘publishResult' for not overwriting the payload.

Finally in the Default flow only add a Set Payload with Display Name ‘Failure Response‘ and Value "The key was not found".

Create a new Flow named ‘subscribe-flow'.

Select from the Mule Palette the Subscribe method from Redis and drag it to the flow as a source:

Add the Redis Configuration.

In Channels select ‘Edit inline' and add a new value named ‘changes' that corresponds to the publisher.

Add a Logger with the Display Name "Publish Message" and the Message equal to payload.

1. Test the POST method.

The URL we will be using is:

http://localhost:8081/api/redis

We will post this JSON:

{
 "key": "one-key",
 "value": "one-value"
}

And the result is as expected:

2. Test the simple GET method.

We are going to search for the Key "one-key" that we've just posted.

The URL we will be using is :

http://localhost:8081/api/redis?key=one-key

We can see here the URL and the response:

3. Test the DELETE method.

We are going to delete the Key "one-key".

The URL we will be using is :

http://localhost:8081/api/redis?key=one-key

The result:

And if we try to delete again the response will be "The key was not found".

4. Test PUBLISH and SUBSCRIBE Methods.

While running the application go to the Client and delete a key.

Same as you did in the last step (the delete needs to be successful).

When a key is deleted, the subscriber should be notified.

Now go to Studio and select Console. You should now see the logger message processor INFO:

Objective: We are going to connect to the mocking service (American Flights API) of Training Mulesoft. The idea is to enrich the response, the JSON, with some new values.

1. Modify the first Transform Message to obtain the ID from the URI parameters:

Paste this code in the output:

%dw 2.0
output application/java
---
attributes.uriParams.ID

Change the Variable name to flightID:

2. Add an HTTP Request:

Add a request URL with the ID at the end:

"https://anypoint.mulesoft.com/mocking/api/v1/sources/exchange/assets/68ef9520-24e9-4cf2-b2f5-620025690913/training-american-flights-api/2.0.1/m/flights/"
++ vars.flightID

In the Headers section add the client_id, client_secret and the Accept condition :

output application/java
---
{
        "client_id" : "1111", 
        "client_secret": "1111", 
        "Accept": "application/json"
}

The Request should look like this:

3. Add another Transform Message to extract the IDs and name it Extract IDs:

Change the output to variable and name ir keys:

Paste this code in the variable output:

%dw 2.0
output application/java
---
[
        payload.origin, 
        payload.destination,
        payload.plane.'type'
]

4. Add a Parallel For Each:

In the section Collection in Settings add vars.keys and in Target add values:

5. Add a Get value method from Redis in the For Each:

Add the Redis Configuration and the payload as the Key:

6. Finally edit the last Transform Message.

Paste this code in the Output section:

%dw 2.0
output application/json
var valueObjects = vars.values.*payload map (read($ default "\"\"", "application/json"))
---
{
  "ID": vars.flightID,
  "code": payload.code,
  "price": payload.price,
  "departureDate": payload.departureDate,
  "origin": payload.origin,
  "originDesc": valueObjects[0],
  "destination": payload.destination,
  "destinationDesc": valueObjects[1],
  "emptySeats": payload.emptySeats,
  "plane": {
    "type": payload.plane.'type',
    "totalSeats": payload.plane.totalSeats, 
    "services": valueObjects[2]
  }
}

1. Send a GET Request to this URL (specifying any ID):

http://localhost:8081/api/flight/24

This should be the result, with the ID matched from the URL:

There are some missing values in this larger JSON. We are going to add them.

2. Add the originDesc:

http://localhost:8081/api/redis
{
 "key": "ORD",
 "value": "Orlando"
}

3. Add the destinationDesc:

http://localhost:8081/api/redis
{
 "key": "SFO",
 "value": "San Francisco"
}

4. Add the services part to the "Boeing 747" plane:

http://localhost:8081/api/redis
{
 "key": "Boeing 747",
 "value": {
   "toilets": 8
 }
}

5. Take a look at the final result with all added. Making a Get Request again:

http://localhost:8081/api/flight/24