APDevFundamentals Studentmanual

Download as pdf or txt
Download as pdf or txt
You are on page 1of 353

Anypoint Platform

Development:
Fundamentals
Student Manual

Mule runtime 4.4


October 27, 2022

1
Table of Contents
INTRODUCING THE COURSE ................................................................................................ 4
Walkthrough: Set up your computer for class ................................................................................................. 5

MODULE 1: ACCESSING AND MODIFYING MULE EVENTS ............................................. 12


Walkthrough 1-1: View event data................................................................................................................ 13
Walkthrough 1-2: Debug a Mule application ................................................................................................. 20
Walkthrough 1-3: Track event data as it moves in and out of a Mule application .......................................... 28
Walkthrough 1-4: Set request and response data ........................................................................................ 35
Walkthrough 1-5: Get and set event data using DataWeave expressions .................................................... 39
Walkthrough 1-6: Set and get variables ....................................................................................................... 47

MODULE 2: STRUCTURING MULE APPLICATIONS .......................................................... 51


Walkthrough 2-1: Create and reference subflows and private flows ............................................................. 52
Walkthrough 2-2: Pass events between flows using the VM connector ........................................................ 57
Walkthrough 2-3: Encapsulate global elements in a separate configuration file............................................ 66
Walkthrough 2-4: Use property placeholders in connectors ......................................................................... 75
Walkthrough 2-5: Create a well-organized Mule project ............................................................................... 79
Walkthrough 2-6: Manage metadata for a project......................................................................................... 89

MODULE 3: CONSUMING WEB SERVICES ........................................................................ 97


Walkthrough 3-1: Consume a RESTful web service that has an API (and connector) in Exchange .............. 98
Walkthrough 3-2: Consume a RESTful web service ................................................................................... 110
Walkthrough 3-3: Consume a SOAP web service ...................................................................................... 119
Walkthrough 3-4: Transform data from multiple services to a canonical format .......................................... 130

MODULE 4: CONTROLLING EVENT FLOW ...................................................................... 138


Walkthrough 4-1: Multicast an event .......................................................................................................... 139
Walkthrough 4-2: Route events based on conditions ................................................................................. 146
Walkthrough 4-3: Validate events .............................................................................................................. 159

MODULE 5: HANDLING ERRORS ...................................................................................... 165


Walkthrough 5-1: Explore default error handling ........................................................................................ 166
Walkthrough 5-2: Handle errors at the application level ............................................................................. 174
Walkthrough 5-3: Handle specific types of errors ....................................................................................... 183
Walkthrough 5-4: Handle errors at the flow level ........................................................................................ 188
Walkthrough 5-5: Handle errors at the processor level ............................................................................... 197
Walkthrough 5-6: Map an error to a custom error type ............................................................................... 204
Walkthrough 5-7: Review and integrate with APIkit error handlers ............................................................. 210
Walkthrough 5-8: Set a reconnection strategy for a connector ................................................................... 223

2
MODULE 6: WRITING DATAWEAVE TRANSFORMATIONS ............................................ 224
Walkthrough 6-1: Create transformations with the Transform Message component ................................... 225
Walkthrough 6-2: Transform basic JSON, Java, and XML data structures ................................................. 236
Walkthrough 6-3: Transform complex data structures with arrays .............................................................. 241
Walkthrough 6-4: Transform to and from XML with repeated elements ...................................................... 251
Walkthrough 6-5: Define and use variables and functions .......................................................................... 259
Walkthrough 6-6: Coerce and format strings, numbers, and dates ............................................................. 265
Walkthrough 6-7: Define and use custom data types ................................................................................. 271
Walkthrough 6-8: Use DataWeave functions .............................................................................................. 275
Walkthrough 6-9: Look up data by calling a flow ........................................................................................ 280

MODULE 7: TRIGGERING FLOWS ..................................................................................... 284


Walkthrough 7-1: Trigger a flow when a new file is added to a directory .................................................... 285
Walkthrough 7-2: Trigger a flow when a new record is added to a database and use automatic
watermarking ............................................................................................................................................. 293
Walkthrough 7-3: Schedule a flow and use manual watermarking.............................................................. 304
Walkthrough 7-4: Publish and listen for JMS messages ............................................................................. 317

MODULE 8: PROCESSING RECORDS............................................................................... 325


Walkthrough 8-1: Process items in a collection using the For Each scope ................................................. 326
Walkthrough 8-2: Process records using the Batch Job scope ................................................................... 333
Walkthrough 8-3: Use filtering and aggregation in a batch step .................................................................. 340

3
Introducing the course

In this module, you will:

 Learn about the course format.


 Download the course files.
 Make sure your computer is set up for class.
 Review the course outline.

4
Walkthrough: Set up your computer for class
In this walkthrough, you make sure your computer is set up correctly, so you can complete the class exercises.
You will:

 Download the course files from the MuleSoft Training Learning Management System.
 Make sure Anypoint Studio starts successfully.
 Install Advanced REST client (if you did not already).
 Make sure you have an active Anypoint Platform account.
 Make sure you have a Salesforce developer account and an API security token.

Download student files


1. In a web browser, navigate to http://training.mulesoft.com.
2. Click Login and select Training.

3. Log in to your MuleSoft training account using the email that was used to register you for class.

Note: If you have never logged in before and do not have a password, click the Forgot your password
link, follow the instructions to obtain a password, and then log in.

4. On the Dashboard page, select Instructor-led under Enrollments then locate the card for your class.

5
5. Click the course name to see the course overview page then locate the class details on the right side of
the page.

6. Click the Resources tab then locate the list of course materials on the right side of the page.

6
7. Click the student files link to download the files.
8. On your computer, locate the student files ZIP and expand it.
9. Open the two course snippets.txt files, one for each part of the course.

Note: Keep these files open. You will copy and paste text from them during class.

10. Click the student manuals link to download the manuals.


11. On your computer, locate the student manuals ZIP and expand it to access the two manuals, one for
each part of the course.
12. Click the student slides link to download the slides.

Start Anypoint Studio


13. In your computer's file browser, navigate to where you installed Anypoint Studio and open it.

Note: If you do not have Anypoint Studio, you can download it from
https://www.mulesoft.com/lp/dl/studio. Upon starting Anypoint Studio, users on Windows may get a
popup asking to allow Windows Defender Firewall access for OpenJDK; access should be allowed.

14. In the Workspace Launcher dialog box, look at the location of the default workspace; change the
workspace location if you want.
15. Click OK to select the workspace; Anypoint Studio should open.

Note: If you cannot successfully start Anypoint Studio, make sure that you have enough available
memory (at least 8GB available) to run Anypoint Studio.

7
16. If you get a new features page, click the Continue to Studio button to close it.

17. If you get an Updates Available popup in the lower-right corner of the application, click it and install the
available updates.

Open Advanced REST Client


18. Open Advanced REST Client.

Note: If you do not have Advanced REST Client (or another REST API client) installed, download it now
from https://install.advancedrestclient.com/ and install it.

8
19. Leave Advanced REST client open; you will use it throughout class.

Make sure you have an active Anypoint Platform account


20. In a web browser, navigate to http://anypoint.mulesoft.com/ and log in.

Note: If you do not have an account, sign up for a free, 30-day trial account now. Also, if you get
prompted here or in other parts of the course to enable multi-factor authentication, select Not Now.

21. Click the menu button located in the upper-left in the main menu bar.

22. In the menu that appears, select Access Management.

Note: This will be called the main menu from now on.

9
23. In the left-side navigation, click the Runtime Manager link under Subscription.
24. Check your subscription level and if it is a trial account, make sure it is not expired.

Note: If your trial is expired or will expire during class, sign out and then sign up for a new trial account
now.

Make sure you have a Salesforce developer account and an API security token
25. In the same or another web browser tab, navigate to http://salesforce.com and log in to the Salesforce
CRM.

Note: If you did not sign up for a free developer account yet, go to http://developer.salesforce.com/ and
sign up for one now. You will want to use a free developer account and not your company account (if
you already have one) for class. You will use the API to add new fictitious accounts to it and will
probably not want to add those to your real data.

10
26. In Salesforce, click your avatar at the top of the screen and select Settings.

27. In the left-side navigation, select My Personal Information > Reset My Security Token.
28. If you did not already request a security token, click the Reset Security Token button.
Note: A security token will be sent to your email in a few minutes. You will need this token to make API
calls to Salesforce from your Mule applications.

11
Module 1: Accessing and
modifying Mule events

At the end this module, you should be able to:

 Log event data.


 Debug Mule applications.
 Read and write event properties.
 Write expressions with the DataWeave expression language.
 Create variables.

12
Walkthrough 1-1: View event data
In this walkthrough, you create a new project to use in the next two modules to learn about Mule events and
Mule applications. You will:

 Create a new Mule project with an HTTP Listener and set the event payload.
 View event data in the DataSense Explorer.
 Use a Logger to view event data in the Anypoint Studio console.

Create a new Mule project


1. Return to Anypoint Studio.
2. Select File > New > Mule Project.
3. Set the project name to apdev-examples and click Finish.

Create an HTTP Listener to receive requests


4. In the Mule Palette, select Favorites.
5. Drag an HTTP Listener from the Mule Palette to the canvas.
6. In the Listener properties view, click the Add button next to Connector configuration.
7. In the Global Element Properties dialog box, verify the host value is set to 0.0.0.0 and the port value to
8081.
8. Click OK.

13
9. In the Listener properties view, set the path to /hello.

10. Click the Advanced tab and set the allowed methods to GET.

11. Click the General tab and set the display name to GET /hello.

14
Change the flow name
12. Select the flow.
13. In the apdev-examplesFlow properties view, change the name to helloFlow.

Set the event payload


14. Drag a Set Payload transformer from the Favorites section of the Mule Palette into the process section
of the flow.
15. In the Set Payload properties view, set the display name to Hello.
16. Switch the value to literal mode and set its value to Hello.

Add a Logger
17. Drag a Logger component from the Mule Palette and drop it at the end of the flow.

View event structure and metadata in the DataSense Explorer


18. Select the GET /hello HTTP Listener and locate the DataSense Explorer in the right side of its
properties view.
15
19. In the Input tab, examine Payload and Attributes.

20. Select the Output tab and examine Payload, Attributes, and HttpRequestAttributes.

21. Select the Set Payload component in helloFlow.


22. In the DataSense Explorer, examine Payload and Attributes in the Input tab.

16
23. Select the Output tab and examine Payload and Attributes.

24. Select the Logger component in helloFlow.


25. In the DataSense Explorer, examine Payload and Attributes in the Input tab.
26. Select the Output tab and examine Payload and Attributes.

Run the application and review response data


27. Save the file and run the project.
28. Return to Advanced REST Client and click the button to create a new tab.

Note: You are adding a new tab so that you can keep the request to your American API saved in
another tab for later use.

29. In the new tab, make a GET request to http://localhost:8081/hello; you should see Hello displayed.

View event data in the Anypoint Studio console


30. Return to Anypoint Studio and look at the console.
31. Locate the data displayed by using the Logger.

17
32. Review the event attributes.

Send query parameters with a request


33. Return to Advanced REST Client and add a query parameter with a key of fname and a value of max.
34. Add a second key/value pair of lname and mule.
35. Click Send.

36. Return to Anypoint Studio and look at the console.

18
37. Locate the query parameters in the logged event data.

38. Stop the project.

19
Walkthrough 1-2: Debug a Mule application
In this walkthrough, you debug and step through the code in a Mule application. You will:

 Locate the port used by the Mule Debugger.


 Add a breakpoint, debug an application, and step through the code.
 Use the Mule Debugger to view event properties.
 Pass query parameters to a request and locate them in the Mule Debugger.
 Increase the request timeout for Advanced REST Client.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Locate the port used by the Mule Debugger


1. Return to Anypoint Studio.
2. In the main menu bar, select Run > Debug Configurations.
3. Select apdev-examples in the left menu bar under Mule Applications; you should see that the apdev-
examples project is selected to launch.

20
4. Select the Mule Debug tab; you should see the debugger port is set to 6666 for the project.

Note: If you know you have another program using port 6666 like McAfee on Windows, change this to a
different value. Otherwise, you can test the Debugger first and come back and change the value here
later if there is a conflict.

5. Click Close.

Add a breakpoint
6. Right-click the Set Payload component and select Add breakpoint.

21
Debug the application
7. Right-click in the canvas and select Debug project apdev-examples.

Note: You can also select Run > Debug or click the Debug button in the main menu bar.

8. If you get a Confirm Perspective Switch dialog box, select Remember my decision and click Yes.
9. Look at the console and wait until the application starts.
10. In Advanced REST Client, make another request to
http://localhost:8081/hello?fname=max&lname=mule.

View event data in the Mule Debugger


11. Return to Anypoint Studio and locate the Mule Debugger view.
12. Look at the value of the payload.
13. Expand Attributes and review the values.

22
14. Expand queryParams and review the values.

Step through the application


15. Click the Next processor button.

23
16. Look at the new value of the payload; it should be Hello.

17. Expand Attributes and review the values.


18. Click the Next processor button again to finish stepping through the application.

Use Resume to step to the next breakpoint and then the end of the application
19. Add a breakpoint to the Logger.

24
20. In Advanced REST Client, make another request to
http://localhost:8081/hello?fname=max&lname=mule.
21. In the Mule Debugger, click the Resume button; you should step to the Logger.

22. Click the Resume button again; you should step through the rest of the application.

Cause the HTTP request to timeout


23. In Advanced REST Client, make another request to
http://localhost:8081/hello?fname=max&lname=mule.
24. Do not step through the application and wait (90 seconds by default) for the request to timeout.

Increase the request timeout for Advanced REST Client


25. In the Advanced REST Client main menu, select File then Settings to navigate to the application
settings.

Note: Depending on your platform, accessing the application settings may differ such as
AdvancedRestClient then Preferences.

26. In the application settings, locate the Request timeout setting and click the arrow next to it.

25
27. Change the request timeout to 300 seconds.

28. Click the arrow next to API Client to return to the request.

29. In the main screen, verify the tab with your last failed request is selected.

Switch perspectives
30. Return to Anypoint Studio.
31. Click the Resume button twice to finish stepping through the application.

26
32. Click the Mule Design button in the upper-right corner of Anypoint Studio to switch perspectives.

Note: In Eclipse, a perspective is a specific arrangement of views in specific locations. You can
rearrange the perspective by dragging and dropping tabs and views to different locations. Use the
Window menu in the main menu bar to save and reset perspectives.

33. Leave the project running.

27
Walkthrough 1-3: Track event data as it moves in and out
of a Mule application
In this walkthrough, you call an external resource, which for simplicity is another HTTP Listener in the same
application, so that you can watch event data as it moves in and out of a Mule application. You will:

 Create a second flow with an HTTP Listener.


 Make an HTTP request from the first flow to the new HTTP Listener.
 View the event data as it moves through both flows.

Note: You are making an HTTP request from one flow to another in this exercise only so you can
watch the value of event data as it moves in and out of a Mule application. You will learn how to pass
events between flows within and between Mule applications in the next module.

Starting file
If you did not complete walkthrough 1-1, you can get a starting file here. This file is also located in the solutions
folder of the student files ZIP located in the Course Resources.

Create a second flow with an HTTP Listener


1. Return to apdev-examples.xml.
2. Drag an HTTP Listener from the Mule Palette and drop it in the canvas beneath the first flow.
3. Change the name of the flow to goodbyeFlow.
4. In the Listener view, ensure the connector configuration is set to the existing HTTP_Listener_config.
5. Set the path to /goodbye and the allowed methods to GET.

28
6. Set the display name to GET /goodbye.

7. Add a Set Payload transformer and a Logger to the flow.


8. In the Set Payload properties view, set the display name to Goodbye and then use literal mode to set
the value to Goodbye.

Make an HTTP request


9. From the Mule Palette, drag an HTTP Request to the canvas and drop it before the Logger in
helloFlow.

10. In the Request properties view, set the display name to GET /goodbye.

29
11. Set the path to /goodbye and leave the method set to GET.

12. Click the Add button next to configuration.


13. In the HTTP Request configuration dialog box, set the host to localhost and the port to 8081 and click
OK.

30
View event structure and metadata in the DataSense Explorer
14. In the DataSense Explorer, examine Payload, Attributes, and HttpRequestAttributes on the Input tab.

15. Select the Output tab and examine Payload, Attributes, and HttpResponseAttributes.

Change timeout for HTTP Request response


16. In the properties view for the GET /goodbye HTTP Request, click the Response tab.
17. Set the Response timeout to 300000.

Note: This is being set only for debugging purposes so that the HTTP Request does not timeout when
you are stepping through the application and examining data in the Mule Debugger.

31
Debug the application
18. Save the file to redeploy the application.
19. In Advanced REST Client, send the same request to
http://localhost:8081/hello?fname=max&lname=mule.
20. In the Mule Debugger, step to the GET /goodbye request.

21. Look at the values of the payload and the attributes, including the queryParams.

22. Step into goodbyeFlow.

32
23. Look at the values of the payload and the attributes.

24. Step through the flow until the event returns to the Logger in helloFlow.

25. Look at the values of the payload and the attributes.

26. Step through the rest of the application.

33
Review response data
27. Return to Advanced REST Client and view the return data and the http status code.
28. Select Headers from the options menu above the http status code.
29. Look at the response headers; you should see content-type, content-length, and date headers.

30. Return to Anypoint Studio and switch to the Mule Design perspective.

34
Walkthrough 1-4: Set request and response data
In this walkthrough, you set response and request data for HTTP Listener and HTTP Request operations. You
will:

 View the default setting for a response body.


 Set a response header.
 View the default setting for a request body.
 Set a request query parameter.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

View default response body


1. Return to apdev-examples.xml.
2. Double-click the GET /hello HTTP Listener in helloFlow.
3. In the GET /hello properties view, click the Responses tab.

35
4. In the Response section, locate the expression that sets the response body by default to the value of
the payload.

Set a response header


5. In the Headers section for the response, click the Add button.
6. Set the name to "name" and the value to "Max".
7. Locate the status code field and leave it blank so the default value 200 is returned.
8. Set the reason phrase to Success.

36
Run the application and review response data
9. Save the file to deploy the project.
10. Return to Advanced REST Client and send the same request.
11. In the Mule Debugger, click Resume until you step through the application.
12. In Advanced REST Client, locate the status code and your new reason phrase on the Raw or
Response tab.
13. On the Headers tab, review the response headers; you should now see the new name header.

View default request body


14. Return to Anypoint Studio and switch perspectives.
15. Double-click the GET /goodbye HTTP Request in helloFlow.
16. In the GET /goodbye properties view, locate the Request section on the General tab.
17. On the Body tab, locate the expression that sets the request body by default to the value of the
payload.

37
Set a request query parameter
18. Select the Query Parameters tab and click the Add button.
19. Set the name to "fullName" and the value to "Max Mule".

Debug and verify the query parameter is sent with the request
20. Save the file to redeploy the project.
21. Return to Advanced REST Client and send the same request.
22. Return to the Mule Debugger and step into goodbyeFlow.
23. Expand Attributes and locate the fullName query parameter.

24. Step through the rest of the application.


25. Switch to the Mule Design perspective.
26. Stop the project.

38
Walkthrough 1-5: Get and set event data using DataWeave
expressions
In this walkthrough, you get and set event data using DataWeave expressions. You will:

 Use expressions to set the payload and a logged value.


 Use expressions to set a response header and a request query parameter.
 In expressions, reference values for the event payload and attributes.
 Use the DataWeave upper() function, the concatenation, as, and default operators.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Use an expression to set the payload


1. Return to apdev-examples.xml.
2. Navigate to the properties view for the Goodbye Set Payload transformer in goodbyeFlow.
3. Use expression mode to change the value to an expression.

#['Goodbye']

4. Save the file and run the project.

39
5. In Advanced REST Client, send the same request; you should get the same result of Goodbye as
before.

Use a DataWeave function


6. In Anypoint Studio, return to the Goodbye Set Payload properties view.
7. Inside the brackets and before the string, type the word up and press Ctrl+Spacebar.
8. Ensure auto-completion inserts the upper function.

9. Move the Goodbye string into the parentheses.

#[upper('Goodbye')]

10. Save the file to redeploy the application.


11. In Advanced REST Client, send the same request; the return string should now be in upper case.

Use an expression that references the payload in a Logger


12. Return to Anypoint Studio.
13. Navigate to the properties view for the Logger in helloFlow.
14. Change the display name to payload.

40
15. Type # in the message field and double-click #[payload] in the auto-completion menu.

16. Save the file to redeploy the application.


17. In Advanced REST Client, send the same request.
18. Return to the console in Anypoint Studio; you should see GOODBYE displayed for the second Logger
instead of the entire event object.

Use a string literal and a DataWeave expression in a property value


19. Return to the properties view for the Logger in helloFlow.
20. Switch the message field to literal mode then change the value to display the string Message in front of
the payload.

Message: #[payload]

21. Save the file to redeploy the application.


22. In Advanced REST Client, send the same request.
23. Return to the console in Anypoint Studio; you should see the new string displayed.

24. Return to the properties view for the Logger in helloFlow.

Use the DataWeave concatenation operator


25. Switch the message field to expression mode then change its value so the string is part of the
evaluated expression and use the concatenation operator.

#['Message: ' ++ payload]

41
26. Add \n in front of the message to display it on a new line.

27. Save the file to redeploy the application.


28. In Advanced REST Client, send the same request.
29. Return to the console in Anypoint Studio; you should see the same string displayed on a new line.

Use an expression that references an attribute in a Logger


30. Navigate to the properties view for the Logger in goodbyeFlow.
31. Change the display name to fullName.
32. Switch the message field to expression mode then type the word at and press Ctrl+Spacebar; you
should see auto-completion insert the attributes keyword.
33. At the end of attributes, add a period, type q and double-click queryParams in the auto-completion
menu.

#[attributes.queryParams]

34. Click Apply Changes to redeploy the application.


35. In Advanced REST Client, send the same request.
36. Return to the Anypoint Studio console; you should see an object displayed by the first Logger.

37. Modify the message for the Logger in goodbyeFlow to display the value of the query parameter.

#[attributes.queryParams.fullName]

42
38. Click Apply Changes to redeploy the application.
39. In Advanced REST Client, send the same request.
40. Return to the console; you should now see the value of the parameter displayed.

Use an expression that references an attribute when setting the payload


41. Navigate to the properties view for the Goodbye Set Payload in goodbyeFlow.
42. Use the concatenation operator to also display the value of the query parameter separated by a space.

#[upper('Goodbye') ++ ' ' ++ attributes.queryParams.fullName]

43. Select the Problems tab and review the error.

Use the as operator to coerce the attribute to a String


44. Add the as operator to display the value of the query parameter as a string.

#[upper('Goodbye') ++ ' ' ++ attributes.queryParams.fullName as String]

Note: This step coerces a null value to a String, to avoid UI errors. The recommended way to handle
null values is by using a default value which is explained later in this walkthrough.

45. Click Apply Changes to redeploy the application.


46. In Advanced REST Client, send the same request; you should now also see the name displayed.

Use an expression to set a request header


47. Return to the Anypoint Studio and navigate to the properties view for the GET /goodbye HTTP Request
in helloFlow.
48. In the Request section, select the Query Parameters tab.

43
49. Change the value of fullName to the value of the fname query parameter.

50. Click Apply Changes to redeploy the application.


51. In Advanced REST Client, send the same request; you should now see the name of the fname query
parameter displayed.

Make a request and do not send a query parameter


52. Remove the query parameters and make a request to http://localhost:8081/hello; you should get an
error.

Set a default value in an expression


53. Return to the Anypoint Studio and navigate to the properties view for the Goodbye Set Payload in
goodbyeFlow.
54. Remove as String.
55. Use the default operator to add a default value of Maxine.

#[upper('Goodbye') ++ ' ' ++ (attributes.queryParams.fullName default


'Maxine')]

56. Click Apply Changes to redeploy the application.

44
57. In Advanced REST Client, send the same request; you should now see the default value Maxine
displayed.

Use a query parameter in the expression for a response header


58. Return to the Anypoint Studio and navigate to the properties view for the GET /hello HTTP Listener.
59. Select the Responses tab.
60. Change the name header value to the value of the fname query parameter.

attributes.queryParams.fname

61. Click Apply Changes to redeploy the application.


62. In Advanced REST Client, add an fname query parameter and set it equal to max or some other value
and send the request.
63. Look at the response headers; you should no longer see a name header.

45
Debug and verify the query parameter is sent with the request
64. Return to Anypoint Studio.
65. Stop and then debug the project.
66. Return to Advanced REST Client and send the same request.
67. Return to the Mule Debugger and look at the attributes and query parameters; you should see the
fname query parameter.

68. Step into goodbyeFlow and look at the attributes and query parameters; you should see the fullName
query parameter.

69. Step back to helloFlow and look at the value of the attributes; you should not see any query parameters.

70. Step through the rest of the application.


71. Switch to the Mule Design perspective.

46
Walkthrough 1-6: Set and get variables
In this walkthrough, you create variables associated with an event. You will:

 Use the Set Variable transformer to create a variable.


 Reference a variable in a DataWeave expression.
 Use a variable to dynamically set a response header.
 Use the Mule Debugger to see the value of a variable.
 Track variables across a transport boundary.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Add the Set Variable transformer to the Favorites section of the Mule Palette
1. Return to apdev-examples.xml.
2. In the Mule Palette, select Core.
3. Locate the Set Variable transformer and right-click it and select Add to favorites.

47
Create a variable
4. Drag the Set Variable transformer from the Favorites section of the Mule Palette and drop it after the
GET /hello HTTP Listener in helloFlow.

5. In the Set Variable properties view, set the display name and name to firstName.
6. Set the value to your query parameter, fname.

Use an expression that references the variable to set a response header


7. Return to the properties view for the GET /hello HTTP Listener in helloFlow.
8. Select the Responses tab.
9. Change the name header value from attributes.queryParams.fname to the value of the firstName
variable.

vars.firstName

48
View variables in the Mule Debugger
10. Save the file to redeploy the project in debug mode.
11. In Advanced REST Client, send the same request.
12. In the Mule Debugger, locate and expand the new Variables section; you should see your firstName
variable.

13. Step into goodbyeFlow; you should see no variables in the vars section.

14. Step back to helloFlow; you should see the Variables section again with your firstName variable.

15. Step through the rest of the application.

49
16. Return to Advanced REST Client; you should see the header with the value of the query parameter.

17. Change the value of the query parameter and send another request.
18. In the Mule Debugger, click the Resume button until you step through the application.
19. Return to Advanced REST client; you should see the new query parameter value returned in both the
body and the header.

20. Return to Anypoint Studio and switch perspectives.

50
Module 2: Structuring Mule
applications

At the end of this module, you should be able to:

 Create applications composed of multiple flows and subflows.


 Pass events between flows using asynchronous queues.
 Encapsulate global elements in separate configuration files.
 Specify application properties in a separate properties file and use them in the application.
 Describe the purpose of each file and folder in a Mule project.
 Define and manage application metadata.

51
Walkthrough 2-1: Create and reference subflows and
private flows
In this walkthrough, you continue to work with apdev-examples.xml. You will:

 Extract processors into separate subflows and private flows.


 Use the Flow Reference component to reference other flows.
 Explore event data persistence through subflows and private flows.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Collapse a flow
1. Return to apdev-examples.xml in Anypoint Studio.
2. Click the arrow to the left of the goodbyeFlow to collapse it.

Create a subflow
3. In the Mule Palette, select Core.
4. Drag a Sub Flow scope from the Mule Palette and drop it between the existing flows in the canvas.
5. Right-click the Set Payload transformer in helloFlow and select Remove breakpoint.

52
6. Select the Set Variable and Set Payload transformers in helloFlow and drag them into the subflow.

Reference a subflow
7. Drag a Flow Reference component from the Mule Palette and drop it into helloFlow between the GET
/hello HTTP Listener and the GET /goodbye HTTP Request.
8. In the Flow Reference properties view, set the flow name to apdev-examplesSub_Flow and the display
name to subflow.
9. Change the name of the subflow from apdev-examplesSub_Flow to subflow.
10. In the subflow Flow Reference properties view, notice that value in the Flow name field has been
automatically changed to subflow.

11. Add a breakpoint to the subflow Flow Reference.

53
Extract processors into another flow
12. Right-click the GET /goodbye HTTP Request and select Extract to > Flow.
13. In the Extract Flow dialog box, set the flow name to privateFlow.

14. Click the Metadata Preferences button and review the metadata propagation information.

15. Leave the target Mule configuration set to Current and click OK.
16. Look at the new Flow Reference properties view; set the display name to privateFlow.

54
17. Drag privateFlow above subflow in the canvas.

Debug the application


18. Save the file to redeploy the application in debug mode.
19. In Advanced REST Client, send a request to http://localhost:8081/hello?fname=Maxwell.
20. In the Mule Debugger, step through the application, watching as you step into and out of the flows and
subflows.

21. Step through the rest of the application.


22. In Advanced REST Client, send the same request again.

55
23. In the Mule Debugger, step through the application again, this time watching the values of the
attributes, payload, and variables in each of the flows.

24. Step through the rest of the application.


25. Switch to the Mule Design perspective.

56
Walkthrough 2-2: Pass events between flows using the VM
connector
In this walkthrough, you pass events between flows using asynchronous queues. You will:

 Pass events between flows using the VM connector.


 Explore variable persistence with VM communication.
 Publish content to a VM queue and then wait for a response.
 Publish content to a VM queue without waiting for a response.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Add the VM module to the project


1. Return to apdev-examples.xml.
2. In the Mule Palette, select Add Modules.
3. Select the VM connector in the right side of the Mule Palette and drag and drop it into the left side.

57
4. In the Package Explorer, locate the JAR file for the VM connector.

Add a VM Publish Consume operation


5. In helloFlow, delete the privateFlow Flow Reference.
6. Select VM in the Mule Palette.
7. Select the Publish consume operation and drag and drop it before the Logger in helloFlow.

8. In the Publish consume properties view, change the display name to VM goodbye.

58
9. Click the Add button next to connector configuration.
10. In the queues drop-down menu, select Edit inline then click the Add Queue button.

11. In the Queue dialog box, set the queue name to goodbye and click Finish.

12. In the Global Element Properties dialog box, click OK.

59
13. In the VM goodbye Publish consume properties view, set the queue name to goodbye.

Note: If you do not see the queue name in the drop-down menu, click the refresh icon for it to be
populated and then set it.

14. Set the timeout to 300 seconds for debugging purposes.

Add a VM Listener
15. Expand goodbyeFlow and delete its HTTP Listener.
16. Locate the Listener operation for the VM connector in the right side of the Mule Palette and drag and
drop it in the source section of goodbyeFlow.

60
17. In the VM Listener properties view, change the display name to VM goodbye.
18. Ensure the connector configuration is set to the existing VM_Config then, if necessary, set the queue
name to goodbye.

Debug the application


19. Save the file to redeploy the project in debug mode.
20. In Advanced REST Client, send the same request.
21. In the Mule Debugger, step through the application to the VM Publish consume.

61
22. Look at the payload, attributes, and variables.

23. Step into goodbyeFlow.


24. Look at the payload, attributes, and variables (or lack thereof).

25. Step through the flow until the event returns to helloFlow.

62
26. Look at the payload, attributes, and variables.

27. Step through the rest of the application.


28. Switch perspectives.

Change the VM Publish Consume operation to Publish


29. Delete the VM Publish consume operation in helloFlow.
30. Drag a VM Publish operation from the Mule Palette and drop it before the Logger.

31. In the Publish properties view, set the display name to VM goodbye.

63
32. Ensure the connector configuration is set to the existing VM_Config and the queue name is set to
goodbye.

Debug the application


33. Save the file to redeploy the project in debug mode.
34. In Advanced REST Client, send the same request.
35. In the Mule Debugger, step through the application to the VM Publish operation.
36. Step again; you should step to the Logger in helloFlow.

64
37. Look at the value of the payload.

38. Step again; you should see execution stopped in goodbyeFlow.


39. Step to the end of the application.
40. Return to Advanced REST Client; you should see a response of Hello – not GOODBYE.

41. Return to Anypoint Studio and switch perspectives.


42. Stop the project.

65
Walkthrough 2-3: Encapsulate global elements in a
separate configuration file
In this walkthrough, you refactor your apdev-examples project. You will:

 Create a new configuration file with an endpoint that uses an existing global element.
 Create a configuration file global.xml for just global elements.
 Move the existing global elements to global.xml.
 Create a new global element in global.xml and configure a new connector to use it.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Create a new configuration file


1. Return to the apdev-examples project.
2. In the Package Explorer, right-click the project and select New > Mule Configuration File.
3. In the dialog box, set the name to accounts and click Finish.

4. Drag an HTTP Listener to the canvas from the Mule Palette.


5. In the Listener properties view, set the display name to GET /sfdc.
6. Ensure the connector configuration is set to the existing HTTP_Listener_config.

66
7. Set the path to /sfdc and the allowed methods to GET.

8. Add a Transform Message component to the flow.


9. In the Transform Message properties view, change the output type to application/json and set the
expression to payload.

10. Change the name of the flow to getSFDCaccounts.

11. Switch to the Global Elements view; you should not see any global elements.

67
Create a global configuration file
12. Create a new Mule configuration file called global.xml.

13. In global.xml, switch to the Configuration XML view.


14. Place some empty lines between the start and end mule tags.

Move the existing global elements to the new global configuration file
15. Return to apdev-examples.xml.
16. Switch to the Global Elements view and see there are three configurations.

17. Switch to the Configuration XML view.

68
18. Select and cut the three configuration elements defined before the flows.

Note: If you delete the global elements from the Global Elements view instead, the config-ref values are
also removed from the connector operations and you need to re-add them.

19. Return to the Message Flow view.


20. Return to global.xml.
21. Paste the global elements you cut to the clipboard between the start and end mule tags.

Note: If you are prompted to regenerate ID values, click Yes.

69
22. Switch to the Global Elements view; you should see the three configurations.

Test the application


23. Return to apdev-examples.xml.
24. Select the GET /hello HTTP Listener in helloFlow; the connector configuration should still be set to
HTTP_Listener_config, which is now defined in global.xml.

25. Run the project.


26. In the dialog box, ensure all the resources are selected and click Save 3 of 3.

27. In Advanced REST Client, send the same request; you should still get a response of Hello.

70
Create a new global element for the Salesforce component in global.xml
28. Return to apdev-examples.xml.
29. In the Mule Palette, select Add Modules.
30. Select the Salesforce connector in the right side of the Mule Palette and drag and drop it into the left
side.

31. Locate the new set of Salesforce JAR files in the project.
32. Return to global.xml.
33. In the Global Elements view, click Create.
34. In the Choose Global Type dialog box, select Connector Configuration > Salesforce Config and click
OK.

71
35. In the Global Element Properties dialog box, locate the Connection section and enter your Salesforce
username, password, and security token.

36. Click Test Connection; your connection should be successful.

37. In the Test connection dialog box, click OK.


38. In the Global Element Properties dialog box, click OK; you should now see the new configuration in
global.xml.

72
Add a new Salesforce operation that uses the global configuration
39. Return to the Message Flow view in accounts.xml.
40. In the Mule Palette, select Salesforce.

41. Locate the Query operation in the right side of the Mule Palette and drag and drop it before the
Transform Message component in getSFDCaccounts.

42. In the Query properties view, set the display name to Account.
43. Ensure the connector configuration is set to the existing Salesforce_Config.
44. Return to the course snippets.txt file and copy the Salesforce query.
45. Return to Anypoint Studio and paste the query in the Salesforce query section of the Query properties
view.

73
Test the application
46. Save all the files; the application should successfully redeploy.
47. In Advanced REST Client, send a GET request to http://localhost:8081/sfdc; you should get a list of the
accounts in your Salesforce account.

74
Walkthrough 2-4: Use property placeholders in connectors
In this walkthrough, you introduce properties into your API implementation. You will:

 Create a YAML properties file for an application.


 Configure an application to use a properties file.
 Define and use HTTP and Salesforce connector properties.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Create a properties file


1. Return to the apdev-examples project.
1. Right-click the src/main/resources folder in the Package Explorer and select New > File.
2. Set the file name to config.yaml and click Finish.

Create a Configuration properties global element


3. Return to global.xml.
4. In the Global Elements view, click Create.

75
5. In the Choose Global Type dialog box, select Global Configurations > Configuration properties and click
OK.

6. In the Global Element Properties dialog box, set the file to config.yaml and click OK.

Parameterize the HTTP Listener port


7. In config.yaml, define a property called http.port and set it to 8081.

8. Save the file.


9. Return to global.xml.
10. Double-click the HTTP Listener config global element.

76
11. Change the port from 8081 to the application property, ${http.port}.

12. Click OK.

Parameterize the Salesforce credentials


13. Double-click the Salesforce Config global element.
14. Copy the username value and click OK.
15. Return to config.yaml.
16. Define a property called sfdc.username and set it to your Salesforce username.
17. Add properties for password and token and set them to your values.

18. Save the file.


19. Return to global.xml.
20. Double-click the Salesforce Config global element.
21. Change the values to use the application properties.

77
22. Click Test Connection and make sure it succeeds.

Note: If your connection fails, click OK and then go back and make sure you do not have any syntax
errors in config.yaml and that you saved the file.

23. Click OK.


24. In the Global Element Properties dialog box, click OK.

Test the application


25. Save all files to redeploy the application.
26. In Advanced REST Client, make the same request to http://localhost:8081/sfdc and confirm you still
get data.

27. Return to Anypoint Studio and stop the project.

78
Walkthrough 2-5: Create a well-organized Mule project
In this walkthrough, you create a new project for the Mule United Airlines (MUA) flights application that you will
build during the course and then review and organize its files and folders. You will:

 Create a project based on a new API in Design Center.


 Review the project's configuration and properties files.
 Create an application properties file and a global configuration file for the project.
 Add Java files and test resource files to the project.
 Create and examine the contents of a deployable archive for the project.

Create a new API in Design Center using Import from File


1. Return to Anypoint Platform in a web browser.
2. In Design Center, select the Create new button and select Import from File.

79
3. In the Import from file dialog box, set the project name to MUA Flights API then select the Choose file
button.

4. Browse to your student files and select the MUA Flights API.zip file located in the resources folder.
5. Click Open.
6. Back in the Import from file dialog box, ensure API specification is selected with REST API in its drop-
down menu.

7. Click Import.

80
8. Explore the API; be sure to look at what resources are defined, the name of the query parameters, and
the structure of the Flight data type.

Create a new project to implement this API in Anypoint Studio


9. Return to Anypoint Studio.
10. Right-click in the Package Explorer and select New > Mule Project.
11. In the New Mule Project dialog box, set the project name to apdev-flights-ws.

81
12. Ensure the Download RAML from Design Center tab is selected.

13. On this tab, click the browse button next to Location.

14. Sign into Anypoint Platform if prompted, then, in the Browse Design Center for APIs dialog box, select
MUA Flights API and click OK.

15. In the New Mule Project dialog box, click Finish.

82
Locate the new RAML files in Anypoint Studio
16. In the Package Explorer, expand the folders in the src/main/resources folder of the new the apdev-
flights-ws project; you should see the MUA Flights API files.

17. Open mua-flights-api.raml and review the file.


18. Leave the file open.

Review project configuration files


19. Look at the mua-flights-api.xml file that was created; it should have a get:\flights flow and a post:\flights
flow.
20. Rename mua-flights-api.xml to interface.xml.
21. Create a new Mule configuration file called implementation.xml.

22. Locate log4j2.xml in src/main/resources and open it.

83
23. Review its contents and then close the file.
24. Locate pom.xml in the project and open it.

25. Review its contents.


26. Return to the apdev-examples project and open its pom.xml file.
27. Compare the two pom.xml files.

28. Close both pom.xml files.


29. In the Package Explorer, right-click apdev-examples and select Close Project.

Create a properties file for application properties


30. In the apdev-flights-ws project, right-click src/main/resources and select New > File.
31. In the Create New File dialog box, set the file name to config.yaml and click Finish.
32. In config.yaml, define a property called http.port equal to “8081”.

33. Save and close the file.

84
Create a global configuration file
34. In src/main/mule, create a new Mule configuration file called global.xml.
35. In global.xml, switch to the Global Elements view.
36. Create a new Configuration properties element with the file set to config.yaml.

37. Create a new HTTP Listener config element with the host set to 0.0.0.0 and the port set to the http.port
property.

38. Confirm you now have two global elements defined in global.xml.

39. Save and close the file.


40. Go to the Global Elements view in interface.xml.
41. Delete the mua-flights-api-httpListenerConfig HTTP Listener Configuration.

85
42. Return to the Message Flow view.
43. Select the HTTP Listener in mua-flights-api-main, and in the Listener properties view, ensure the
connector configuration is set to HTTP_Listener_config.

44. Select the HTTP Listener in mua-flights-api-console, and in the Listener properties view, ensure the
connector configuration is set to HTTP_Listener_config.

Add Java files to src/main/java


45. In the Package Explorer, right-click the src/main/java folder and select New > Package.
46. In the New Java Package dialog box, set the name to com.mulesoft.training and click Finish.

47. In your computer's file browser, locate the Flight.java file in the resources folder of the student files.
48. Drag the Flight.java file into the new com.mulesoft.training package in the src/main/java folder in the
apdev-flights-ws project.
49. In the File Operation dialog box, ensure Copy files is selected and click OK.
50. Open the Flight.java file.

51. Review the code.

86
Review src/test folders
52. In the project, locate the three src/test folders.
53. Expand the src/test/resources folder.

Add test resources


54. In your computer's file browser, expand the resources/examples folder in the student files.
55. Select the three flights and one united-flights files (JSON and XML) and drag them into the
src/test/resources folder in the apdev-flights-ws project.
56. In the File Operation dialog box, ensure Copy files is selected and click OK.

Examine the contents of a deployable archive


57. In Anypoint Studio, save all files, and then right-click the project and select Export.
58. In the Export dialog box, select Mule > Anypoint Studio Project to Mule Deployable Archive and click
Next.

87
59. In the Export Mule Project dialog box, set the JAR file to a location that you can find and click Finish.

60. In the Export Mule Project dialog box, click OK.


61. In your computer's file browser, locate the JAR file and expand it.
62. Open the resulting apdev-flights-ws folder and examine the contents.

88
Walkthrough 2-6: Manage metadata for a project
In this walkthrough, you define metadata for the apdev-flights-ws project. You will:

 Review existing metadata for the training4-american-ws project.


 Define new metadata to be used in transformations in the new apdev-flights-ws project.
 Manage metadata.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Locate existing metadata in the training4-american-ws project


1. Open the training4-american-ws project.
2. Locate application-types.xml in src/main/resources.

89
3. Open the file and review the code.

4. Right-click the training4-american-ws project in the Package Explorer and review the options under
Mule; you should see two for metadata.

5. Select Mule > Manage Metadata Types.


6. In the Manage Metadata Types dialog box, select the american_flights_json type.

7. Click OK.
8. Close the project.

90
Review the API specification and resources for the apdev-flights-ws project
9. Return to the apdev-flights-ws project.
10. Return to mua-flights-api.raml and review the specified response and request types.

11. Locate the files you added to the src/test/resources folder.

12. Locate the file you added to the src/main/java folder.

Create flights_json metadata type


13. Right-click the project and select Mule > Manage Metadata Types.
14. In the Manage Metadata Types dialog box, click the Add button.

91
15. In the Create new type dialog box, set the type id to flights_json.

16. Click Create type.


17. In the Manage Metadata Types dialog box, set the first type to JSON.
18. In the drop-down menu beneath the type, select Example.

19. Click the browse button and select the flights-example.json file in src/test/resources.

20. In the Manage Metadata Types dialog box, click OK.

92
21. In the Apply changes dialog box, click Yes.

Locate the new metadata definition file


22. Locate application-types.xml in src/main/resources.

23. Open the file and review the code.

Create flight_json metadata type


24. Right-click the project and select Mule > Manage Metadata Types.
25. In the Manage Metadata Types dialog box, click Add.
26. In the Create new type dialog box, set the type id to flight_json and click Create type.
27. In the Manage Metadata Types dialog box, set the first type to JSON.

93
28. Select Example and browse to and select the flight-example.json file in src/test/resources.

Create flights_xml metadata type


29. In the Manage Metadata Types dialog box, click Add.
30. In the Create new type dialog box, set the type id to flights_xml and click Create type.
31. In the Apply changes dialog box, click Yes.
32. In the Manage Metadata Types dialog box, set the first type to XML.
33. Select Example and browse to and select the flights-example.xml file in src/test/resources.

94
Create Flight_pojo metadata type
34. In the Manage Metadata Types dialog box, click the Add button.
35. In the Create new type dialog box, set the type id to Flight_pojo and click Create type.
36. In the Apply changes dialog box, click Yes.
37. In the Manage Metadata Types dialog box, set the first type to Object.

38. In the Data structure section, click Click here to select an option.
39. In the drop-down menu that appears, select Java object.
40. In the dialog box that opens, type fli in the Select entries field and then in the list of classes that
appears, select Flight – com.mulesoft.training.

95
41. Click OK.

42. In the Manage Metadata Types dialog box, click OK.


43. In the Apply changes dialog box, click Yes.

Review the metadata definition file


44. Return to application-types.xml.

45. Close the file.

96
Module 3: Consuming web
services

At the end of this module, you should be able to:

 Consume web services that have an API (and connector) in Exchange.


 Consume RESTful web services.
 Consume SOAP web services.
 Pass parameters to SOAP web services using the Transform Message component.
 Transform data from multiple services to a canonical format.

97
Walkthrough 3-1: Consume a RESTful web service that has
an API (and connector) in Exchange
In this walkthrough, you consume a pre-built American flights RESTful web service that has an API and a
connector in Exchange. You will:

 Create a new flow to call the American RESTful web service.


 Add a REST connector from Exchange to an Anypoint Studio project.
 Configure and use a REST connector to make a call to a web service.
 Dynamically set a query parameter for a web service call.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Examine the REST connectors for the pre-built Training: American Flights API in
Exchange
1. Navigate to Exchange in Anypoint Platform.
2. Locate the Training: American flights API in the public Exchange.

Note: If you still have access to the American Flights API you created in the Getting Started with
Anypoint Platform course, you are encouraged to review and use that API instead in the steps that
follow. If you do not have access to port 3306, using your API (or, if necessary, a new API created
using the Derby Database connector option detailed in Walkthrough 4-2 of the Getting Started course)
is required. In order to use your API, you'll need its client credentials and endpoint URL.
98
3. Select the API and review its information.

4. Click the Download drop-down menu button; you should see that REST Connect has created
connectors for the API in Exchange.

Make a request to the web service


5. Return to the course snippets.txt file and copy the value for the Training: American Flights API client_id.
6. Return to Advanced REST Client, select the first tab, and add a header called client_id.
7. Set client_id to the value you copied from the snippets.txt file.
8. Repeat for client_secret.

99
9. Send a GET request to the Training: American Flights API http://training4-american-
api.cloudhub.io/flights; you should see JSON data for the American flights as a response.

Note: The client credentials in the snippets file may be different than what is shown here; the values in
the snippets file differ for instructor-led and self-study training classes.

Add a new flow with an HTTP Listener


10. Return to the apdev-flights-ws project in Anypoint Studio.
11. Return to implementation.xml.
12. Drag out an HTTP Listener and drop it in the canvas.
13. Rename the flow to getAmericanFlights.
14. In the Listener properties view, set the display name to GET /american.
15. Ensure the connector configuration is set to the existing HTTP_Listener_config.

100
16. Set the path to /american.
17. Set the allowed methods to GET.

Add the American Flights API module to Anypoint Studio


18. In the Mule Palette, select Search in Exchange.
19. In the Add Dependencies to Project dialog box, enter american in the search field.

20. Select the Training - American Flights API and click Add.
21. Click Finish.
22. Wait for the module to be downloaded.
23. Select the new American Flights API module in the Mule Palette.

101
Add a Get all flights operation
24. Select the Get flights operation in the right side of the Mule Palette and drag and drop it in the process
section of the flow.

25. Select the Get flights operation in the canvas and in its properties view, see that you need to create a
new configuration and enter a client_id and client_secret.

Configure the American Flights API connector


26. Open global.xml.
27. In the Global Elements view, click Create.

102
28. In the Choose Global Type dialog box, select Connector Configuration > American Flights API Config
and click OK.

29. In the Global Element Properties dialog box, set each field to a corresponding property placeholder
(that you will define and set next):

 host: ${american.host}
 port: ${american.port}
 protocol: ${american.protocol}
 basePath: ${american.basepath}

30. Click OK.


31. Return to the course snippets.txt file and copy the text for the American RESTful web service
properties.

103
32. Open config.yaml in src/main/resources and paste the code at the end of the file.

33. Return to Advanced REST Client and copy the value for your client_id.
34. Return to config.yaml and paste the value within double quotes.
35. Repeat for your client_secret.

Configure the Get flights operation


36. Return to implementation.xml.
37. In the Get flights properties view, ensure the Connector configuration is set to
American_Flights_API_Config.
38. Set the client id to the ${american.client_id} property.
39. Set the client secret to the ${american.client_secret} property.
40. Leave the destination field blank.

104
Review metadata associated with the operation
41. Select the output tab in the DataSense Explorer and expand Payload.

Test the application


42. Run the project.
43. In the dialog box, ensure all the resources are selected and click Save 3 of 3.

44. In Advanced REST Client, return to the tab with the localhost request.

105
45. Change the URL to make a GET request to http://localhost:8081/american; you should get all the
flights.

Review the specification for the API you are building


46. Return to mua-flights-api.raml in src/main/resources/api.
47. Review the optional query parameters.

106
48. Locate the return type for the get method of the /flights resource.

49. Open FlightsExample.raml in src/main/resources/api.examples and review its structure.

Create a variable to set the destination airport code


50. Return to implementation.xml.
51. Drag a Sub Flow scope from the Mule Palette and drop it at the top of the canvas.
52. Change the name of the flow to setCode.
53. Drag a Set Variable transformer from the Mule Palette and drop it in the setCode subflow.

54. In the Set Variable properties view, set the name and display name to code.

107
55. Switch the value field to expression mode then set its value to a query parameter called code and give
it a default value of SFO if no query parameter is passed to the flow.

message.attributes.queryParams.code default 'SFO'

Dynamically set a query parameter for the web service call


56. Drag a Flow Reference component from the Mule Palette and drop it after the GET /american Listener
in getAmericanFlights.
57. In the Flow Reference properties view, set the flow name and display name to setCode.

58. In the Get flights properties view, switch the destination field to expression mode then set its value to
the variable containing the airport code.

vars.code

108
Test the application
59. Save the file to redeploy the application.
60. In Advanced REST Client, send the same request; this time you should only get flights to SFO.

61. Add query parameter called code equal to LAX and make the request; you should now only see flights
to LAX.

62. Examine the data structure of the JSON response.

Note: You will transform the data to the format specified by the mua-flights-api in a later walkthrough.

109
Walkthrough 3-2: Consume a RESTful web service
In this walkthrough, you consume the United RESTful web service that does not have an API in Exchange.
You will:

 Create a new flow to call the United RESTful web service.


 Use the HTTP Request operation to call a RESTful web service.
 Dynamically set a URI parameter for a web service call.
 Add metadata for an HTTP Request operation’s response.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Make a request to the United web service


1. Return to the course snippets.txt file.
2. Locate and copy the United RESTful web service URL.
3. In Advanced REST Client, make a new tab and make a GET request to this URL.
4. Review the structure of the JSON response.

110
5. Look at the destination values; you should see SFO, LAX, CLE, PDX, and PDF.
6. In the URL field, add the destination CLE as a URI parameter:
http://mu.learn.mulesoft.com/united/flights/CLE.
7. Send the request; you should now only see flights to CLE.

Add a new flow with an HTTP Listener operation


8. Return to implementation.xml in Anypoint Studio.
9. Drag out an HTTP Listener from the Mule Palette and drop it at the bottom of the canvas.
10. Change the name of the flow to getUnitedFlights.
11. In the Listener properties view, set the display name to GET /united.
12. Ensure the connector configuration is set to the existing HTTP_Listener_config.
13. Set the path to /united.
14. Set the allowed methods to GET.

Add an HTTP Request operation


15. Drag out an HTTP Request from the Mule Palette and drop it into the process section of
getUnitedFlights.

16. In the Request properties view, set the display name to Get flights.

111
Create an HTTP Request configuration
17. Return to the course snippets.txt file and copy the text for the Training web service properties.
18. Return to config.yaml and paste the code at the end of the file.

Note: The Training web service properties you see may be different than what is shown here; the
values in the snippets file differ for instructor-led and self-study training classes.

19. Return to the Global Elements view in global.xml.


20. Create a new HTTP Request configuration with the following values:

 Name: HTTP_Request_config_training
 Base Path: ${training.basepath}
 Host: ${training.host}
 Port: ${training.port}

21. Click OK.

112
Configure the HTTP Request operation
22. Return to implementation.xml.
23. Navigate to the Get flights Request properties view in getUnitedFlights.
24. Set the configuration to the existing HTTP_Request_config_training.
25. Leave the method set to GET.
26. Set the path to /united/flights.

Review metadata associated with the United Get flights operation response
27. Select the Output tab in the DataSense Explorer; you should see no metadata for the payload.

Test the application


28. Save the files to redeploy the project.
29. In Advanced REST Client, return to the tab with the localhost request.

113
30. Change the URL to make a GET request to http://localhost:8081/united; you should get JSON flight
data for all destinations returned.

31. Add a query parameter named code and set it to one of the destination airport code values:
http://localhost:8081/united?code=CLE; you should still get flights to all destinations.

Add a URI parameter to the web service call


32. Return to implementation.xml in Anypoint Studio.
33. Drag a Flow Reference component from the Mule Palette and drop it after the GET /united Listener in
getUnitedFlights.
34. In the Flow Reference properties view, set the flow name and display name to setCode.

114
35. Navigate to the Get flights Request properties view in getUnitedFlights.
36. In the Request section, change the path to /united/flights/{dest}.

37. Select the URI Parameters tab.


38. Click the Add button.
39. Set the name to dest.
40. Set the value to the value of the code variable.

vars.code

115
Test the application
41. Save the file to redeploy the application.
42. In Advanced REST Client, make the same request; you should now only get flights to CLE.

43. Remove the code parameter and make the request; you should now only get results for SFO.

Note: You will transform the data to the format specified by the mua-flights-api in a later walkthrough.

Add metadata for the United Get flights operation response


44. Return to Anypoint Studio.
45. Navigate to the properties view for the Get flights operation in getUnitedFlights.
46. Select the Output tab in the DataSense Explorer and examine Payload; you should still see no
metadata for the payload.

116
47. In the Get flights properties view, select the Metadata tab.
48. Click the Add metadata button.

49. Change the drop-down menu to Output: Payload.


50. Click the Edit button.

51. In the Select metadata type dialog box, click the Add button.
52. In the Create new type dialog box, set the type id to united_flights_json.
53. Click Create type.
54. In the Select metadata type dialog box, set the first type to JSON.
55. Change the Schema selection to Example.
56. Click the browse button and navigate to the projects's src/test/resources folder.

117
57. Select united-flights-example.json and click Open; you should see the example data for the metadata
type.

58. Click Select.


59. In the DataSense Explorer, ensure the Output tab is selected and expand Payload; you should now see
the structure for the payload.

118
Walkthrough 3-3: Consume a SOAP web service
In this walkthrough, you consume a Delta SOAP web service. You will:

 Create a new flow to call the Delta SOAP web service.


 Use a Web Service Consumer connector to consume a SOAP web service.
 Use the Transform Message component to pass arguments to a SOAP web service.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Browse the WSDL


1. Return to the course snippets.txt file and copy the Delta SOAP web service WSDL.
2. In Advanced REST Client, return to the tab with the learn.mulesoft request.
3. Paste the URL and send the GET request; you should see the web service WSDL returned.
4. Browse the WSDL; you should find references to operations listAllFlights and findFlight.

119
Create a new flow with an HTTP Listener connector endpoint
5. Return to Anypoint Studio.
6. Drag out another HTTP Listener from the Mule Palette and drop it in the canvas after the existing flows.
7. Rename the flow to getDeltaFlights.

8. In the Listener properties view, set the display name to GET /delta.
9. Ensure the connector configuration is set to the existing HTTP_Listener_config.
10. Set the path to /delta and the allowed methods to GET.

Add the Web Service Consumer module to the project


11. In the Mule Palette, select Add Modules.
12. Select the Web Service Consumer connector in the right side of the Mule Palette and drag and drop it
into the left side.

120
13. If you get a Select module version dialog box, select the latest version and click Add.

Configure the Web Service Consumer connector


14. Return to the course snippets.txt file and copy the text for the Delta web service properties.
15. Return to config.yaml in src/main/resources and paste the code at the end of the file.

Note: The Delta web service properties you see may be different than what is shown here; the values in
the snippets file differ for instructor-led and self-study training classes.

16. Save the file.


17. Return to global.xml.
18. Click Create.

121
19. In the Choose Global Type dialog box, select Connector Configuration > Web Service Consumer
Config.

20. Click OK.


21. In the Global Element Properties dialog box, change the name to
Delta_Web_Service_Consumer_Config.
22. Set the following values:

 Wsdl location: ${delta.wsdl}


 Service: ${delta.service}
 Port: ${delta.port}

23. Click OK.

122
Add and configure a Consume operation
24. Return to implementation.xml.
25. Locate the Consume operation for the Web Service Consumer connector in the Mule Palette and drag
and drop it in the process section of getDeltaFilghts.

26. In the Consume properties view, change its display name to Get flights.
27. Ensure the connector configuration is set to the existing Delta_Web_Service_Consumer_Config.
28. Click the operation drop-down menu; you should see the web service operations listed.
29. Select the listAllFlights operation.

123
Review metadata associated with the Delta Get flights operation response
30. Select the Output tab in the DataSense Explorer and expand Payload; you should see the payload
structure.

Test the application


31. Save the files and wait for the application to redeploy.
32. In Advanced REST Client, return to the tab with the localhost request.
33. Make a GET request to http://localhost:8081/delta; you should get a 200 status code and a response
listing the contents of listAllFlightsResponse.

124
Transform the response to JSON
34. Return to Anypoint Studio.
35. Add a Transform Message component to the end of the flow.
36. Set the display name to SOAP to JSON.

37. In the Transform Message properties view, change the output type to application/json and set the
expression to payload.

Test the application


38. Save the file to redeploy the project.
39. In Advanced REST Client, make another request to http://localhost:8081/delta then examine the
Response tab; you should get JSON returned.

125
40. Click the Raw tab; you should see all the flights.

41. Add a query parameter called code and set it equal to LAX.
42. Send the request; you should still get all flights.

Call a different web service operation


43. Return to the getDeltaFlights flow in Anypoint Studio.
44. In the properties view for Get flights Consume operation, change the operation to findFlight.

126
Review metadata associated with the Delta Get flights operation response
45. Select the Output tab in the DataSense Explorer and expand Payload; you should now see the payload
metadata for findFlightResponse.

46. Select the Input tab and expand Payload; you should see this operation now expects a destination.

Test the application


47. Save the file to redeploy the project.
48. In Advanced REST Client, send the same request with the query parameter; you should get a 500
Server Error with a message that the operation requires input parameters.

127
Use the set airport code subflow
49. Return to the getDeltaFlights flow in Anypoint Studio.
50. Add a Flow Reference component after the GET /delta Listener.
51. In the Flow Reference properties view, set the flow name and display name to setCode.

Use the Transform Message component to pass a parameter to the web service
52. Add a Transform Message component after the Flow Reference component.
53. Change its display name to Pass code.

54. In the Pass code properties view, look at the input and output sections.
55. Drag the code variable in the input section to the destination element in the output section.

128
Test the application
56. Save the file to redeploy the application.
57. In Advanced REST Client, make another request; you should now only see flights to LAX.

129
Walkthrough 3-4: Transform data from multiple services to
a canonical format
In this walkthrough, you will transform the JSON returned from the American and United web services and the
SOAP returned from the Delta web service to the same format. You will:

 Define a metadata type for the Flight Java class.


 Transform the results from RESTful and SOAP web service calls to a collection of Flight objects.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Review Flight.java
1. Return to apdev-flights-ws in Anypoint Studio.
2. Return to Flight.java in src/main/java and review the file.

3. Close the file.

Change the American flow to return Java Flight objects instead of JSON
4. Return to getAmericanFlights in implementation.xml.
5. Add a Transform Message component to the end of the flow.
6. Add a Logger at the end of the flow.

130
7. Change the name of the Transform Message component to JSON to [Flight].

8. In the Transform Message properties view, look at the input section; you should see metadata already
defined.

9. In the output section of the Transform Message properties view, click the Define metadata link.
10. In the Select metadata type dialog box, select the user-defined Flight_pojo.
11. Select Wrap element in a collection in the lower-left corner.

131
12. Click Select; you should now see output metadata in the output section of the Transform Message
properties view.
13. Map fields (except ID and totalSeats) by dragging them from the input section and dropping them on
the corresponding field in the output section.

14. Double-click the airlineName field in the output section.


15. In the generated DataWeave expression, change the airlineName value from null to "American".

Test the application


16. Save the file to redeploy the project.
17. In Advanced REST Client, change the URL and make a request to http://localhost:8081/american; you
should see a representation of a collection of Java objects.

132
Debug the application
18. Return to Anypoint Studio.
19. Stop the project.
20. Add a breakpoint to the Get flights operation in getAmericanFlights.
21. Debug the project.
22. In Advanced REST Client, make another request to http://localhost:8081/american.
23. In the Mule Debugger, step to the Transform Message component and examine the payload.

24. Step to the Logger and look at the payload it should be a collection of Flight objects.

25. Step through the rest of the application and switch perspectives.

133
Change the United airline flows to return Java Flight objects instead of JSON
26. Return to getUnitedFlights in implementation.xml.
27. Add a Transform Message component at the end of the flow.
28. Change the name of the Transform Message component to JSON to [Flight].
29. Add a Logger to the end of the flow.

30. In the Transform Message properties view, look at the input section; you should see metadata already
defined.
31. In the output section of the Transform Message properties view, click the Define metadata link.
32. In the Select metadata type dialog box, select the user-defined Flight_pojo.
33. Select Wrap element in a collection in the lower-left corner.
34. Click Select; you should now see output metadata in the output section of the Transform Message
properties view.

134
35. Map fields by dragging them from the input section and dropping them on the corresponding field in the
output section.

Debug the application


36. Add a breakpoint to the Transform Message component.
37. Save the file to redeploy the project.
38. In Advanced REST Client, change the URL to make a request to http://localhost:8081/united.
39. In the Mule Debugger, examine the payload.

40. Step to the Logger and look at the payload it should be a collection of Flight objects.

41. Step through the rest of the application and switch perspectives.

135
Change the Delta flow to return Java Flight objects
42. Return to geDeltaFlights in implementation.xml.
43. Change the name of the SOAP to JSON Transform Message component to SOAP to [Flight].
44. Add a Logger to the end of the flow.

45. Look at the input section in the SOAP to [Flight] Transform Message properties view; you should see
metadata already defined.
46. In the output section of the Transform Message properties view, click the Define metadata link.
47. In the Select metadata type dialog box, select the user-defined Flight_pojo.
48. Select Wrap element in a collection in the lower-left corner.
49. Click Select; you should now see output metadata in the output section of the Transform Message
properties view.
50. Map the fields by dragging them from the input section and dropping them on the corresponding field in
the output section.

Debug the application


51. Add a breakpoint to the SOAP to [Flight] Transform Message component.
52. Save the file to redeploy the project.
53. In Advanced REST Client, change the URL to make a request to http://localhost:8081/delta.

136
54. In the Mule Debugger, examine the payload.

55. Step to the Logger and look at the payload it should be a collection of Flight objects.

56. Step through the rest of the application and switch perspectives.

137
Module 4: Controlling event flow

At the end of this module, you should be able to:

 Multicast events.
 Route events based on conditions.
 Validate events.

138
Walkthrough 4-1: Multicast an event
In this walkthrough, you create a flow that calls each of the three airline services and combines the results. You
will:

 Use a Scatter-Gather router to concurrently call all three flight services.


 Use DataWeave to flatten multiple collections into one collection.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Create a new flow


1. Return to implementation.xml in the apdev-flights-ws project in Anypoint Studio.
2. From the Mule Palette, drag an HTTP Listener and drop it at the top of the canvas.
3. Change the flow name to getAllAirlineFlights.
4. In the Listener properties view, set the display name to GET /flights.
5. Ensure the connector configuration is set to the existing HTTP_Listener_config.
6. Set the path to /flights and the allowed methods to GET.

139
Browse the flow control elements in the Mule Palette
7. In the Core section of the Mule Palette, locate the Flow Control elements.

Add a Scatter-Gather to call all three airline services


8. Drag a Scatter-Gather flow control element from the Mule Palette and drop it in the process section of
getAllAirlineFlights.
9. Add three parallel Flow Reference components to the Scatter-Gather router.
10. In the first Flow Reference properties view, set the flow name and display name to getAmericanFlights.
11. Set the flow name and display name of the second Flow Reference to getUnitedFlights.
12. Set the flow name and display name of the third Flow Reference to getDeltaFlights.
13. Add a Logger after the Scatter-Gather.

140
Review the metadata for the Scatter-Gather output
14. In the Logger properties view, explore the input payload structure in the DataSense Explorer.

Debug the application


15. Add a breakpoint to the Scatter-Gather.
16. Add a breakpoint to the Logger.
17. Save the file to redeploy the project in debug mode.
18. In Advanced REST Client, change the URL to make a request to http://localhost:8081/flights.

141
19. In the Mule Debugger, step through the application; you should step through each of the airline flows.

20. Stop at the Logger after the Scatter-Gather and explore the payload.

142
21. Drill-down into one of the objects in the payload.

22. Step through the rest of the application and switch perspectives.
23. Return to Advanced REST Client and review the response; you should get a 500 Server Error with a
message that the object could not be serialized.

Flatten the combined results


24. Return to Anypoint Studio.
25. In getAllAirlineFlights, add a Transform Message component before the Logger.
26. Change the display name to flatten to [Flight].

143
27. In the input section of the Transform Message properties view, review the payload data structure.

28. In the expression section, use the DataWeave flatten function to flatten the collection of objects into a
single collection.

Debug the application


29. Save the file to redeploy the project.
30. In Advanced REST Client, make the same request to http://localhost:8081/flights.

144
31. In the Mule Debugger, press Resume until you are stopped at the Logger at the end of the Scatter-
Gather; you should see the payload is now one ArrayList of Flights.

32. Step through the rest of the application and switch perspectives.

145
Walkthrough 4-2: Route events based on conditions
In this walkthrough, you create a flow to route events to either the American, United, Delta, or get all airline
flows based on the value of an airline query parameter. You will:

 Use a Choice router.


 Use DataWeave expressions to set the router paths.
 Route all flight requests through the router.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Look at possible airline values specified in the API


1. Return to the apdev-flights-ws project in Anypoint Studio.
2. Return to mua-flights-api.raml in src/main/resources/api.
3. Locate the airline query parameter and its possible values.

146
Create a new flow
4. Return to implementation.xml.
5. Drag a Flow scope from the Mule Palette and drop it at the top of the canvas above all the other flows.
6. Change the name of the flow to getFlights.
7. Move the GET /flights HTTP Listener from getAllAirlineFlights to the source section of getFlights.

Add a Choice router


8. Drag a Choice flow control element from the Mule Palette and drop it in process section of getFlights.

9. Add three parallel Flow Reference components to the Choice router.


10. Add a Flow Reference component to the default branch of the router.
11. In the first Flow Reference properties view, set the flow name and display name to getAmericanFlights.
12. Set the flow names and display names for the other two Flow References to getUnitedFlights and
getDeltaFlights.

147
13. For the Flow Reference in the default branch, set the flow name and display name to
getAllAirlineFlights.

Store the airline query parameter in a variable


14. Add a Set Variable transformer before the Choice router.

148
15. In the Set Variable properties view, set the name and display name to airline.
16. Switch the value field to expression mode then set its value to a query parameter called airline.

message.attributes.queryParams.airline

Configure the Choice router


17. In the Choice router getAmericanFlights flow reference branch, click the When scope.
18. In the When properties view, switch the value field to expression mode, and then add an expression to
check if the airline variable is equal to american.

vars.airline == "american"

19. Set a similar expression for the United route, routing to it when vars.airline is equal to united.

149
20. Set a similar expression for the Delta route, routing to it when vars.airline is equal to delta.

Route all requests through the router


21. Add a Flow Reference to the flow before the Choice router.

150
22. Set the flow name and display name to setCode.

23. In getAmericanFlights, delete the HTTP Listener and the setCode Flow Reference.

24. In getUnitedFlights, delete the HTTP Listener and the setCode Flow Reference.

25. In getDeltaFlights, delete the HTTP Listener and the setCode Flow Reference.

Return JSON from the flow


26. In the getFlights flow, add a Transform Message component after the Choice router.
27. Change its display name to [Flight] to JSON.

151
28. Add a Logger at the end of the flow.

29. In the Transform Message properties view, change the output type to application/json and set the
expression to payload.

Debug the application


30. Add a breakpoint to the airline Set Variable transformer at the beginning of getFlights.
31. Add a breakpoint to the [Flight] to JSON Transform Message component after the Choice router.
32. Save the file to redeploy the project in debug mode.
33. In Advanced REST Client, make a request to http://localhost:8081/flights.

152
34. In the Mule Debugger, step through the application; you should see the Choice router pass the event to
the default branch.

35. Resume to the Transform Message component after the Choice router; the payload should be an
ArrayList of Flight objects
36. Step to the Logger; the payload should be JSON.
37. Step to the end of the application.

153
38. Return to Advanced REST Client; you should see American, United, and Delta flights to SFO (the
default airport code).

39. Add an airline query parameter set to american and send the request:
http://localhost:8081/flights?airline=american.

154
40. In the Mule Debugger, step through the application; you should see the event passed to
getAmericanFlights and then back to getFlights.

41. Return to Advanced REST Client; you should see only American flights to SFO returned.

42. Change the airline to united and add a second query parameter code set to LAX:
http://localhost:8081/flights?airline=united&code=LAX.

155
43. Send the request.
44. In the Mule Debugger, step through the application; the event should be routed to the United branch.

45. Return to Advanced REST Client; you should see only United flights to LAX are returned.

46. Change the airline to delta and the code to PDX: http://localhost:8081/flights?airline=delta&code=PDX.
47. Send the request.

156
48. In the Mule Debugger, step through the application; the event should be routed to the Delta branch.

49. Return to Advanced REST Client; you should see only Delta flights to PDX are returned.

Note: This JSON structure does not match that specified in the API: mua-flights-api.raml in
src/main/resources/api. The data should, of course, be transformed so the response from the API
matches this specification – but we are going to hold off doing that right now so that the scenario stays
simpler for the error handling module (there is one less error to handle at the beginning).

Test the application with a destination that has no flights


50. Remove the airline parameter and set the code to FOO: http://localhost:8081/flights?code=FOO.
51. Send the request.

157
52. In the Mule Debugger, step through the application; you should see multiple errors.

53. Return to Advanced REST Client; you should get a 500 Server Response and an exception.

158
Walkthrough 4-3: Validate events
In this walkthrough, you use a validator to check if a query parameter called code with a value of SFO, LAX,
CLE, PDX, or PDF is sent with a request and to throw an error if it is not. You will:

 Add the Validation module to a project.


 Use an Is true validator to check if a query parameter called code with a value of SFO, LAX, CLE, PDX,
or PDF is sent with a request.
 Return a custom error message if the condition is not met.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Add the Validation module to the project


1. Switch to the Mule Design perspective and return to implementation.xml.
2. In the Mule Palette, select Add Modules.
3. Select the Validation module in the right side of the Mule Palette and drag and drop it into the left side.
4. If you get a Select module version dialog box, select the latest version and click Add.

159
Use the Is true validator to check for a valid destination code
5. Locate the Is true validator in the right side of the Mule Palette.
6. Drag and drop the Is true validator after the setCode Flow Reference in the getFlights flow.

7. In the Is true properties view, set the display name to Is valid destination.
8. Change the expression from False (Default) to Expression.
9. Add a DataWeave expression to check if the code variable is one of the five destination codes.

#[['SFO','LAX','CLE','PDX','PDF'] contains vars.code]

Note: You can copy this expression from the course snippets.txt file.

10. Using expression mode, set the error message to Invalid destination followed by the provided code.

'Invalid destination' ++ ' ' ++ (vars.code default ' ')

Note: You can copy this expression from the course snippets.txt file.

Debug the application


11. Save the file and wait for the application to redeploy.
12. In Advanced REST Client, change the code to make a request to
http://localhost:8081/flights?code=CLE.

160
13. In the Mule Debugger, step past the validator; you should see the code is valid and application
execution steps to the Choice router.

14. Resume through the rest of the application.


15. In Advanced REST Client, you should see flights for CLE.

16. Change the code and make a request to http://localhost:8081/flights?code=FOO.


17. In the Mule Debugger, attempt to step past the validator; you should see an error.

161
18. Resume through the rest of the application; you should see your Invalid destination message in the
console.

19. Return to Advanced REST Client; you should get a 500 Server Error with your Invalid destination
message.

Note: You will catch this error and send a JSON response with a different status code in the next
module.

20. Remove the code and make a request to http://localhost:8081/flights.


21. In the Mule Debugger, step past the validator; you should not get any errors.

162
22. Resume through the rest of the application.
23. Return to Advanced REST Client; you should get a 200 response with all airline flights to SFO.

24. Return to Anypoint Studio and switch to the Mule Design perspective.

Remove the default destination


25. Locate the setCode subflow.
26. In the Set Variable properties view, review the default value.

27. Remove the default value from the value.

Debug the application


28. Save the file to redeploy the project.
29. In Advanced REST Client, make another request to http://localhost:8081/flights.

163
30. In the Mule Debugger, attempt to step past the validator; you should now get an error.

31. Resume through the rest of the application.


32. Return to Advanced REST Client; you should get a 500 Server Error with your Invalid destination
message.

Note: You will catch this error and send a JSON response with a different status code in the next
module.

33. Return to Anypoint Studio and stop the project.

164
Module 5: Handling errors

At the end of this module, you should be able to:

 Handle messaging errors at the application, flow, and processor level.


 Handle different types of errors, including custom errors.
 Use different error scopes to either handle an error and continue execution of the parent flow or propagate
an error to the parent flow.
 Set the success and error response settings for an HTTP Listener.
 Set reconnection strategies for system errors.

165
Walkthrough 5-1: Explore default error handling
In this walkthrough, you get familiar with the three errors you will learn to handle in this module. You will:

 Explore information about different types of errors in the Mule Debugger and the console.
 Review the default error handling behavior.
 Review and modify the error response settings for an HTTP Listener.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Create a connectivity error


1. Return to apdev-flights-ws in Anypoint Studio.
2. Return to config.yaml.
3. Change the delta.wsdl property from /delta?wsdl to /deltas?wsdl.

4. Save the file.


5. Return to implementation.xml and debug the project.
6. If you get an Errors in Workspace dialog box, click Proceed.

166
Review a validation error in the Mule Debugger and console
7. In Advanced REST Client, add a code and make a request to http://localhost:8081/flights?code=FOO.
8. In the Mule Debugger, step to where the error is thrown and examine the error object; you should see
an error description, errorType, and other properties.

9. Step through the rest of the application and review the error information logged in the console.

10. In Advanced REST Client, locate the response status code, status reason, and body; you should see a
500 status code, a status reason of Server Error, and a response body equal to the error description.

Review a connectivity error in the Mule Debugger and console


11. Add an airline and change the code to make a request to
http://localhost:8081/flights?airline=delta&code=PDX.

167
12. In the Mule Debugger, step to where the error is thrown and review the error object.

13. Step again and review the error information logged in the console.
14. Step through the rest of the application.
15. Return to Advanced REST Client; you should see a 500 Server Error with the error description.

Review a bad request error in the Mule Debugger and console


16. Change the airline to make a request to http://localhost:8081/flights?airline=american&code=PDX.
17. In the Mule Debugger, step to where the error is thrown and review the error object.

18. Step through the rest of the application.

168
19. Review the error information logged in the console.
20. Return to Advanced REST Client; you should see a 500 Server Error with the error description.

21. Return to Anypoint Studio and switch to the Mule Design perspective.
22. Stop the project.

Review the default error response settings for an HTTP Listener


23. Navigate to the properties view for the GET /flights Listener in getFlights.
24. Select the Responses tab.
25. Locate the Error Response section and review the default settings for the body, status code, and
reason phrase.

169
Remove the default error response settings for the HTTP Listener
26. Select and cut the body expression (so it has no value, but you can paste it back later).

Test the application


27. Save the file, run the project, and proceed through any errors in the workspace.
28. In Advanced REST Client, make another request to
http://localhost:8081/flights?airline=american&code=PDX; you should get the same response.

Modify the default error response settings for the HTTP Listener
29. Return to Anypoint Studio.
30. Return to the Responses tab in the properties view for the GET /flights Listener.
31. In the error response body, paste back the original value.

output text/plain --- error.description

32. Change the output type of the error response to application/json and display the error.errorType.

output application/json --- error.errorType

Note: Ensure the error response body is in expression mode.

170
33. Set the error response status code to 400.

Test the application


34. Save the file to redeploy the application.
35. In Advanced REST Client, make another request to
http://localhost:8081/flights?airline=american&code=PDX; you should get the new status code and
reason and the response body should be the errorType object.
36. Look at the error namespace and identifier.

171
37. Change the airline to make a request to http://localhost:8081/flights?airline=delta&code=PDX.
38. Look at the error namespace and identifier.

39. Change the code to make a request to http://localhost:8081/flights?airline=delta&code=FOO.


40. Look at the namespace and identifier.

172
Return the default error response settings for the HTTP Listener
41. Return to Anypoint Studio.
42. Return to the Responses tab in the properties view for the GET /flights Listener.
43. Change the error response output type back to text/plain and display the error.description.

output text/plain --- error.description

44. Remove the status code.

Test the application


45. Save the file to redeploy the application.
46. In Advanced REST Client, change the airline and code to make a request to
http://localhost:8081/flights?airline=american&code=PDX; you should get the 500 Server Error again
with the plain text error description.

47. Return to Anypoint Studio.


48. Stop the project.

173
Walkthrough 5-2: Handle errors at the application level
In this walkthrough, you create a default error handler for the application. You will:

 Create a global error handler in an application.


 Configure an application to use a global default error handler.
 Explore the differences between the On Error Continue and On Error Propagate scopes.
 Modify the default error response settings for an HTTP Listener.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Browse the error handling elements in the Mule Palette


1. Return to global.xml and switch to the Message Flow view.
2. In the Core section of the Mule Palette, locate the Error Handling elements.

Create a global error handler with an On Error Continue scope


3. Drag out an Error Handler element and drop it in the canvas of global.xml.

174
4. Drag out an On Error Continue element and drop it in globalError_Handler.

5. In the On Error Continue properties view, click the search button for type.
6. In the drop-down menu that appears, select ANY.

Set the payload in the error handler to a JSON message


7. Add a Transform Message component to the On Error Continue.
8. Set the Transform Message display name to error.description.

9. In the Transform Message properties view, change the output type to application/json.

175
10. Add a message property to the output JSON and give it a value of the error.description.

Set a default error handler for the application


11. Switch to the Global Elements view of global.xml.
12. Click Create.
13. In the Choose Global Type dialog box, select Global Configurations > Configuration and click OK.

14. In the Global Element Properties dialog box, set the default error handler to globalError_Handler and
click OK.

15. Switch to the Message Flow view.

Review the default response settings for an HTTP Listener


16. Return to implementation.xml.
17. Navigate to the properties view for the GET /flights Listener in getFlights.

176
18. Select the Responses tab.
19. Locate the Response section (not the Error Response section) and review the default settings for the
body, status code, and reason phrase.

20. Locate the Error Response section and review the default settings for the body, status code, and
reason phrase.

Test the On Error Continue behavior


21. Save all files, debug the project, and proceed through any errors in the workspace.
22. In Advanced REST Client, make another request to
http://localhost:8081/flights?airline=american&code=PDX.
23. In the Mule Debugger, step through the application until the event is passed to globalError_Handler.
24. Expand the error object and review the exception.

177
25. Step again; the event should be passed back to getFlights, which continues to execute after the error
occurs.
26. Review the payload and note the absence of an error object.

27. Resume through the rest of the application.


28. Return to Advanced REST Client; you should see a 200 OK response with the response body equal to
the payload value set in the error handler.

Change the default error handler to use an On Error Propagate scope


29. Return to Anypoint Studio and switch to the Mule Design perspective.
30. Return to global.xml.

178
31. Drag an On Error Propagate element from the Mule Palette and drop it to the right or left of the On
Error Continue to add it to globalError_Handler.

32. In the On Error Propagate properties view, set the type to ANY.
33. Move the Transform Message component from the On Error Continue to the On Error Propagate.
34. Delete the On Error Continue scope.

Test the On Error Propagate behavior


35. Save the file to redeploy the project.
36. In Advanced REST Client, make another request to
http://localhost:8081/flights?airline=american&code=PDX.
37. Step through the application until the event is passed to globalError_Handler.
38. Look at the error object in the Mule Debugger; it should be the same as before.
39. Step again; the error is propagated up to the getFlights parent flow.

179
40. Look at the payload and the error object in the Mule Debugger.

41. Step twice more; the error is handled by the application’s default error handler again.
42. Look at the payload and the error object in the Mule Debugger.
43. Resume through the rest of the application.
44. Return to Advanced REST Client; you should see get a 500 Server Error response with the response
body equal to the plain text error description – not the payload.

45. Return to Anypoint Studio and switch to the Mule Design perspective.
46. Stop the project.

Modify the default error response settings for the HTTP Listener
47. Return to implementation.xml.
48. Navigate to the Responses tab in the properties view for the GET /flights Listener.

180
49. Change the error response body to return the payload instead of error.description.

payload

Test the application


50. Save the file, run the project, and proceed through any errors in the workspace.
51. In Advanced REST Client, make another request to
http://localhost:8081/flights?airline=american&code=PDX; you should now get the message that you
set in the error handler.

Note: You will handle this error differently in a later walkthrough, so it does not return a server error. It is
a valid request; there are just no American flights to PDX.

181
52. Change the airline to make a request to http://localhost:8081/flights?airline=delta&code=PDX; the error
is handled by the same default handler.

53. Return to Anypoint Studio.

182
Walkthrough 5-3: Handle specific types of errors
In this walkthrough, you continue to work with the application’s default error handler. You will:

 Review the possible types of errors thrown by different processors.


 Create error handler scopes to handle different error types.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Review the possible types of errors thrown by a Web Service Consumer operation
1. Return to implementation.xml.
2. Navigate to the properties view for the Get flights Consume operation in getDeltaFlights.
3. Select the Error Mapping tab.
4. Click the Add new mapping button and review (but don’t select!) the WSC error types.

183
Review the possible types of errors thrown by a REST Connector operator
5. Navigate to the properties view for the Get flights operation in getAmericanFlights.
6. Select the Error Mapping tab.
7. Click the Add new mapping button, and review (but don’t select!) the AMERICAN-FLIGHTS-API error
types.

Review the possible types of errors thrown by a Validator operation


8. Navigate to the properties view for the Is true validator in getFlights.
9. Select the Error Mapping tab.
10. Click the Add new mapping button and locate (but don’t select!) the VALIDATION error type.

184
Add a second error handler scope to catch Web Service Consumer connectivity errors
11. Return to global.xml.
12. Add a second On Error Propagate to globalError_Handler.
13. If necessary, drag and drop it so it is the first scope inside the error handler.

14. Return to the course snippets.txt file and copy the expression for the error type.
15. Return to global.xml in Anypoint Studio.
16. In the properties view for the new On Error Propagate, set the error type by pasting the expression you
copied.

WSC:CONNECTIVITY, WSC:INVALID_WSDL

185
17. Add a Transform Message component to the new On Error Propagate and set its display name to Data
unavailable.

18. In the Transform Message properties view, change the output type to application/json.
19. Add a message property to the output JSON and set give it a value of "Data unavailable. Try later. ".
20. For development purposes, concatenate the error.description to the message; be sure to use the auto-
completion menu.
21. Coerce the variable to a String.

186
Test the application
22. Save the file to redeploy the project.
23. In Advanced REST Client, make another request to
http://localhost:8081/flights?airline=delta&code=PDX; you should now get a 500 Server Error response
with your new Data unavailable message.

24. Change the code to make a request to http://localhost:8081/flights?airline=delta&code=FOO; you


should still get a 500 Server Error response with the Invalid destination JSON message.

Note: This should also not be a server error, but either a 4XX bad request or a 200 OK with an
appropriate message. You will handle this error differently in the next walkthrough.

25. Return to Anypoint Studio.


26. Stop the project.

187
Walkthrough 5-4: Handle errors at the flow level
In this walkthrough, you add multiple error handlers to a flow. You will:

 Add error handlers to a flow.


 Test the behavior of errors thrown in a flow and by a child flow.
 Compare On Error Propagate and On Error Continue scopes in a flow.
 Set an HTTP status code in an error handler and modify an HTTP Listener to return it.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Add an On Error Propagate error handler to a flow


1. Return to implementation.xml.
2. Expand the Error handling section of the getFlights flow.
3. Add an On Error Propagate scope.

188
4. Set the error type to ANY so it will initially catch both the validation and American flights errors.

Set the payload in the error handler to the error description


5. Add a Transform Message component to the scope and set the display name to No flights.
6. In the Transform Message properties view, set the payload to a JSON message property equal to the
string No flights to and concatenate the code variable.
7. Coerce the variable to a String.

Set the HTTP status code in the error handler to 200


8. Add a Set Variable transformer to the On Error Propagate.
9. In the Set Variable properties view, set the display name and name to httpStatus.
10. Set the value to 200.

189
Set the HTTP Listener error response status code to use a variable
11. Navigate to the Responses tab in the properties view for the GET /flights Listener.
12. Use expression mode to change the error response status code (not the response status code!) to an
expression that sets it equal to the value of an httpStatus variable with a default value of 500.

vars.httpStatus default 500

Test the flow’s On Error Propagate with an error in the flow


13. Save the file, debug the project, and proceed through any errors in the workspace.
14. In Advanced REST Client, change the airline to make a request to
http://localhost:8081/flights?airline=american&code=FOO.
15. In the Mule Debugger, step until the event is passed to the flow’s error handler.

16. Step through the rest of the application.


17. Return to Advanced REST Client; you should get the 200 status code and the JSON message.

190
Test the flow’s On Error Propagate with an error in a child flow
18. In Advanced REST Client, change the code to make a request to
http://localhost:8081/flights?airline=american&code=PDX.
19. Step until the event is passed to the globalError_Handler.

20. Step until the error is passed to the parent flow’s error handler.

191
21. Step through the rest of the application.
22. Return to Advanced REST Client; you should get the 200 status code and the JSON error message.

23. Return to Anypoint Studio and switch to the Mule design perspective.

Specify the type of error to be handled by the flow’s error handler


24. Navigate to the properties view for the On Error Propagate in getFlights.
25. Change the type from ANY to AMERICAN-FLIGHTS-API:BAD_REQUEST.

Test the application


26. Save the file to redeploy the project.
27. In Advanced REST Client, make another request to
http://localhost:8081/flights?airline=american&code=PDX.
28. In the Mule Debugger, step through the application; the error should still be handled by
globalError_Handler and then the getFlights flow error handler.

29. In Advanced REST Client, change the code to make a request to


http://localhost:8081/flights?airline=american&code=FOO.

192
30. In the Mule Debugger, step through the application; you should get a 500 Server Error and no message
because the error is not handled by the getFlights flow error handler or by globalError_handler.

31. Return to Anypoint Studio and switch to the Mule Design perspective.
32. Stop the project.
33. Navigate to the Responses tab in the properties view for the GET /flights Listener.
34. Review the error response body (not the response body!) and ensure you know why you got the last
response for http://localhost:8081/flights?airline=american&code=FOO.

Use an On Error Continue error handler in a flow


35. Add an On Error Continue scope to getFlights.
36. In the On Error Continue properties view, set the type to VALIDATION:INVALID_BOOLEAN.

37. Add a Transform Message component to the scope and set the display name to error.description.
38. In the Transform Message properties view, set the payload to a JSON message property equal to the
error.description.

39. Add a Set Variable transformer to the On Error Continue scope.

193
40. Set the display name and name to httpStatus and set the value to 400.

Test the application


41. Save the file, run the project, and proceed through any errors in the workspace.
42. In Advanced REST Client, make another request to
http://localhost:8081/flights?airline=american&code=FOO; you should get a 200 response and the
invalid destination message again – not the 400 response.

Set the HTTP Listener response status code


43. Return to Anypoint Studio.
44. Navigate to the Responses tab in the properties view for the GET /flights Listener.
45. Use expression mode to set the response status code (not the error response status code!) to an
expression that sets it equal to the value of an httpStatus variable with a default value of 200.

vars.httpStatus default 200

Test the application


46. Save the file to redeploy the project.

194
47. In Advanced REST Client, make another request to
http://localhost:8081/flights?airline=american&code=FOO; you should now get the 400 response.

Test the application to see what happens with the Scatter-Gather


48. In Advanced REST Client, change the code and make a request to
http://localhost:8081/flights?airline=american&code=PDX; you should get a 200 response and no flights
to PDX.
49. Change the airline to make a request to http://localhost:8081/flights?airline=united&code=PDX; you
should get United flights to PDX.

195
50. Remove the airline to make a request to http://localhost:8081/flights?code=PDX; you should get flights
to PDX because United has flights, but you get none.

51. Return to Anypoint Studio.


52. Stop the project.

196
Walkthrough 5-5: Handle errors at the processor level
In this walkthrough, you work with the Scatter-Gather in getAllAirlineFlights so that it correctly returns results
when one but not all airlines have flights. You will:

 Wrap the Flow Reference in each branch of a Scatter-Gather in a Try scope.


 Use an On Error Continue scope in each Try scope error handler to provide a valid response so flow
execution can continue.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Debug the application when a Scatter-Gather branch has an error


1. Return to implementation.xml in Anypoint Studio.
2. Debug the project and proceed through any errors in the workspace.
3. In Advanced REST Client, make another request to http://localhost:8081/flights?code=PDX.
4. Return to the Mule Debugger and step through the application until you see a routing exception.

197
5. Step through the rest of the application.
6. Return to Advanced REST client, you should get the 500 Server Error that there were exceptions in
routes 0 and 2.

7. Return to Anypoint Studio and switch to the Mule Design perspective.

Place each Flow Reference in the Scatter-Gather in a Try scope


8. Locate the getAllAirlineFlights flow.
9. Drag a Try scope from the Mule Palette and drop it in the Scatter-Gather before the getAmericanFlights
Flow Reference.

10. Drag the getAmericanFlights Flow Reference into the Try scope.
11. Add Try scopes to the other two routes of the Scatter-Gather.

198
12. Move the getUnitedFlights Flow Reference into one of the Try scopes and the getDeltaFlights Flow
Reference into the other.

Add an error handler to each branch that passes through the error message
13. Expand the error handling section of the first Try scope.
14. Add an On Error Continue scope and set the types of errors it handles to ANY.
15. Repeat these steps to add the same error handler to the two other Try scopes.

199
Debug the application
16. Save the file to redeploy the project.
17. In Advanced REST Client, make another request to http://localhost:8081/flights?code=PDX.
18. In the Mule Debugger, resume to the Logger after the Scatter-Gather in getAllAirlineFlights.
19. Expand Payload; you should see three flights (from United) and two error messages.

20. Step through the rest of the application.


21. Return to Advanced REST Client; you should see United flights and error messages.

200
Modify each error handler to set the payload to an empty array
22. Return to Anypoint Studio and switch to the Mule Design perspective.
23. In getAllAirlineFlights, add a Transform Message component to one of the On Error Continue scopes.
24. Set the display name to [].

25. In the Transform Message properties view, set the payload to an empty array.

201
26. Repeat the steps to add the same Transform Message component to the two other error handlers.

Debug the application


27. Save the file to redeploy the project.
28. In Advanced REST Client, make another request to http://localhost:8081/flights?code=PDX.
29. In the Mule Debugger, resume to the Logger after the Scatter-Gather in getAllAirlineFlights.

202
30. Expand Payload; you should now see the three flights and no error messages.

31. Step through the rest of the application.


32. Return to Advanced REST Client; you should now only see the three flights.

33. Return to Anypoint Studio and switch to the Mule Design perspective.
34. Stop the project.

203
Walkthrough 5-6: Map an error to a custom error type
In this walkthrough, you map the Validation error to a custom error type for the application. You will:

 Map a module error to a custom error type for an application.


 Create an event handler for the custom error type.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Map a validation module error to a custom error type


1. Return to implementation.xml.
2. Navigate to the properties view for the validator in getFlights.
3. Select the Error Mapping tab.
4. Click the Add new mapping button.

5. Select the VALIDATION:INVALID_BOOLEAN error type.


6. Leave the namespace of the custom error to map to set to APP.

204
7. Set the identifier to INVALID_DESTINATION.

8. Press Enter; you should see your new error mapping.

Change the existing validation error handler to catch the new custom type
9. Navigate to the properties view for the getFlights validation On Error Continue error handler.

10. Change the type from VALIDATION:INVALID_BOOLEAN to the new APP:INVALID_DESTINATION


that should now appear in the type drop-down menu.

205
Test the application
11. Save the file, run the project, and proceed through any errors in the workspace.
12. In Advanced REST Client, change the code and make a request to
http://localhost:8081/flights?code=FOO; you should still get a 400 response with the invalid destination
error.

Move the American error handler into the American flow


13. Collapse the getAllAirlineFlights and setCode flows.
14. Move the AMERICAN-FLIGHTS-API error scope from getFlights into getAmericanFlights.

Move the error handler to the global error handler


Note: The following steps have instructions to make changes in the XML. If you prefer, you can copy and paste
the error handler to move it between files and then delete the original.

15. Right-click the validation On Error Continue error handler in getFlights and select Go to XML.

206
16. Select and cut the APP:INVALID_DESTINATION on-error-continue.

17. Delete the remaining, empty error-handler tag set.

18. Return to global.xml.


19. Right-click the globalError_Handler and select Go to XML.
20. Place the cursor on a new line inside and at the start of the globalError_Handler error-handler.
21. Paste the on-error-continue you cut to the clipboard.

Note: If you are prompted to regenerate ID values, click Yes.


207
22. Switch back to the Message Flow view; you should see the APP:INVALID_DESTINATION handler.

23. Return to implementation.xml and switch to the Message Flow view; you should no longer see an error
handler in getFlights.

208
Test the application
24. Save the files to redeploy the project.
25. In Advanced REST Client, make another request to http://localhost:8081/flights?code=FOO; you should
still get a 400 response with the invalid destination error.

26. Change the code and make a request to http://localhost:8081/flights?code=PDX; you should still get
only United flights to PDX.

209
Walkthrough 5-7: Review and integrate with APIkit error
handlers
In this walkthrough, you connect the application’s implementation to the interface and ensure all the error
handling works. You will:

 Review the error handlers generated by APIkit.


 Review settings for the APIkit Router and HTTP Listener in the APIkit generated interface.
 Connect the implementation to the interface and test the error handling behavior.
 Modify implementation error scopes so they work with the APIkit generated interface.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Review APIkit generated error handlers


1. Return to apdev-flights-ws in Anypoint Studio.
2. Return to interface.xml.

210
3. Review the error handling section in mua-flights-api-main.

4. Review the types of errors handled by each error handler scope.


5. Navigate to the Transform Message properties view for the first error handling scope.
6. Review the expression that sets the payload.

7. Use the output drop-down menu to change the output to Variable – httpStatus.

8. Review the expression that sets an httpStatus variable; you should see that for a bad request the
httpStatus variable is set to 400.

211
Review settings for the APIkit Router
9. Navigate to the properties view for the APIkit Router in mua-flights-api-main.

10. Click the Edit button next to router configuration.

11. In the Global Element Properties dialog box, locate the HTTP status var name setting; you should see
httpStatus.

12. Click OK.

212
Review settings for the HTTP Listener
13. Navigate to the Responses tab in the properties view for the HTTP Listener in mua-flights-api-main.
14. Review the response body and status code.

15. Review the error response body and status code.

Connect the interface to the implementation


16. In interface.xml, locate the get:\flights flow.

17. Review the default transformation in this flow.


18. Delete the Transform Message component.
19. Add a Flow Reference component to the flow.

213
20. In the Flow Reference properties view, set the flow name and display name to getFlights.

21. Return to implementation.xml.


22. Delete the GET /flights Listener in getFlights.

23. Save all the files to redeploy the application.

214
Test the application
24. In Advanced REST Client, make another request to http://localhost:8081/flights?code=PDX; you should
get a 404 response with a no listener message.

25. Add /api to the URL and make a request to http://localhost:8081/api/flights?code=PDX; you should get
the United flights to PDX as before.

26. Change the code to make a request to http://localhost:8081/api/flights?code=FOO; you should now get
a 400 Bad Request response instead of your custom message.

215
27. Remove the code to make a request to http://localhost:8081/api/flights; you should now get your
custom error message.

28. Add the airline and code to make a request to


http://localhost:8081/api/flights?airline=american&code=PDX; you should now get a 200 response with
the bad request description in the error message.

Review the API


29. Return to Anypoint Studio and stop the project.
30. Return to mua-flights-api.raml and review the code; you should see the code query parameter is not
required but it has allowed values enumerated.

216
Debug the application
31. Return to interface.xml.
32. Add a breakpoint to the APIkit Router in mua-flights-api-main.
33. Debug the project and proceed through any errors in the workspace.
34. In Advanced REST Client, make another request to
http://localhost:8081/api/flights?airline=american&code=PDX.
35. In the Mule Debugger, watch the payload and variables and step through the application.
36. Step back to the APIkit router.
37. Review the exception, the payload, and the variables.

38. Resume through the rest of the application.


39. In Advanced REST Client, change the code to make a request to
http://localhost:8081/api/flights?airline=american&code=FOO.
40. In the Mule Debugger, step through the application; the APIkit router should immediately throw an error.

217
41. Step again; you should see the error is handled by the APIKIT:BAD_REQUEST handler.

42. Resume through the rest of the application.


43. In Advanced REST Client, remove the airline and code to make a request to
http://localhost:8081/api/flights.
44. In the Mule Debugger, step through the application; the validator should throw an error and execution
should not return to the APIkit router.
45. Return to Advanced REST Client; you should get a 400 response with the custom message.

Note: If you had specified the code query parameter to be required in the RAML file from which the
interface was generated, the APIkit router would catch this immediately and respond with a 400 Bad
Request response. The event would never get to the validator in your implementation.

Change the American flights error scope to On Error Continue


46. Return to Anypoint Studio and switch to the Mule Design perspective.
47. Return to implementation.xml.

218
48. Locate the error handler in the getAmericanFlights flow.

49. Right-click it and select Go To XML.


50. Change the on-error-propagate start and end tags in the getAmericaFlights flow to on-error-continue.

51. Change the doc:name in the start tag to On Error Continue.


52. Switch back to the Message Flow view; you should now see an On Error Continue.

219
Change the global default error scopes to On Error Continue
53. Return to global.xml.
54. Review the types of error handler scopes.

55. Right-click the WSC error handler and select Go To XML.


56. Change the four on-error-propagate start and end tags to on-error-continue.
57. Change the doc:names in both start tags to On Error Continue.
58. Switch back to the Message Flow view; you should now see both are On Error Continue scopes.

220
Set the HTTP status code for the On Error Continue scopes so you do not get 200
59. Add a Set Variable transformer to the WSC error handler.
60. In the Set Variable properties view, set the display name and name to httpStatus.
61. Set the value to 500.
62. Copy the Set Variable transformer and add it to the ANY error scope.

Test the application


63. Save the files to redeploy the project.
64. In Advanced REST Client, add the airline and code to make a request to
http://localhost:8081/api/flights?airline=american&code=PDX.

221
65. In the Mule Debugger, step through the application; the application now does not return to the APIkit
router.
66. Return to Advanced REST Client; you should now get a 200 response with the No flights to PDX
message.

67. In Advanced REST Client, change the airline to make a request to


http://localhost:8081/api/flights?airline=delta&code=PDX.
68. In the Mule Debugger, step through the application.
69. Return to Advanced REST Client; you should now get the 500 response with the data unavailable
message.

70. Return to Anypoint Studio and switch perspectives.

222
Walkthrough 5-8: Set a reconnection strategy for a
connector
In this walkthrough, you will:

 Set a reconnection strategy for the Web Service Consumer connector.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Set a reconnection strategy for a connector


1. Return to global.xml in Anypoint Studio.
2. Switch to the Global Elements view.
3. Double-click the Web Service Consumer Config.

4. In the Global Element Properties dialog box, select the Advanced tab in the second tab bar.
5. Select the Reconnection checkbox.
6. Change the reconnection strategy to standard.
7. Review the default frequency and attempts.

8. Click OK.
9. Save the file.

223
Module 6: Writing DataWeave
transformations

At the end of this module, you should be able to:

 Write DataWeave expressions for basic XML, JSON, and Java transformations.
 Write DataWeave transformations for complex data structures with repeated elements.
 Define and use global and local variables and functions.
 Use DataWeave functions.
 Coerce and format strings, numbers, and dates.
 Define and use custom data types.
 Call Mule flows from DataWeave expressions.
 Store DataWeave scripts in external files.

224
Walkthrough 6-1: Create transformations with the
Transform Message component
In this walkthrough, you create a new flow that receives flight POST requests that you will use as the input for
writing transformations in the next several walkthroughs. You will:

 Create a new flow that receives POST requests of JSON flight objects.
 Customize propagated metadata.
 Add sample data and use live preview.
 Create a second transformation that stores the output in a variable.
 Save a DataWeave script in an external file.
 Review DataWeave script errors.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Create a new flow that receives POST requests and returns the payload as Java
1. In the apdev-flights-ws Mule project, return to config.yaml.
2. Change the delta.wsdl property from /deltas?wsdl to /delta?wsdl.
3. Return to implementation.xml.
4. Right-click in the canvas and select Collapse All.
5. Drag a Transform Message component from the Mule Palette to the bottom of the canvas; a new flow
should be created.
6. Change the name of the flow to postFlight.
7. In the Transform Message properties view, set the expression to payload.

Note: If you see a metadata propagation error on the Transform Message, you can proceed normally.

8. Add a breakpoint to the Transform Message component.


225
9. Add a Logger to the flow.

10. Return to interface.xml.


11. Remove the breakpoint from the APIkit Router in mua-flights-api-main.
12. Locate the post:\flights:application\json:mua-flights-api-config flow.
13. Delete the Transform Message component and replace it with a Flow Reference.
14. In the Flow Reference properties view, set the flow name and display name to postFlight.

15. Save the files to redeploy the project in debug mode.

Post a flight to the flow


16. Open flight-example.json in src/test/resources.
17. Copy the code and close the file.
18. In Advanced REST Client, change the method to POST and remove any query parameters.
19. Add a request header called Content-Type and set it equal to application/json.
20. Set the request body to the value you copied from flight-example.json.
21. Make the request to http://localhost:8081/api/flights.

226
22. In the Mule Debugger, expand Attributes and locate the content-type header.
23. Review the payload; you should see it has a mime-type of application/json.

24. Step to the Logger; you should see the payload now has a mime-type of application/java and is a
LinkedHashMap.

25. Step to the end of the application and switch perspectives.

227
Customize the transformation input metadata propagated from the API specification
26. Examine the input section of the Transform Message properties view; note the field for the optional ID
property.

27. Return to interface.xml.


28. In the postFlight Flow Reference properties view, select the Metadata tab.
29. Click the Add metadata button.
30. Ensure the drop-down menu is set to Input: Payload and click the Edit button.
31. In the Select metadata type dialog box, select flight_json and click Select.

32. On the Metadata tab, click the Set metadata button.


33. In the Custom metadata dialog box, click Customize.

228
34. In the Custom Metadata dialog box, locate and expand the expected payload on the Input Metadata
tab; note the absence of the optional ID property.

35. Click OK.


36. Save and close the file.
37. In the Transform Message properties view for the transformation in postFlight; you should now see
updated metadata for the input.

38. Open application-types.xml in src/main/resources.


39. Review the enrichment elements for flight_json.

40. Close the file.

229
Preview sample data and sample output
41. In the input section of the Transform Message properties view, right-click the payload and select Edit
Sample Data; you should see a new tab called payload and it should contain the sample input of type
JSON.
42. Click the Preview button; you should see a new preview section and it should contain the sample output
of type Java.

If sample data doesn't automatically appear in the preview section, click the Create required sample
data to execute preview link.

43. Click the Source Only button to the left of the Preview button.

Locate the new sample data file


44. In the Package Explorer, locate the new sample_data folder in src/test/resources.

45. Open json.json.


46. Review the code and close the file.

230
Create a second transformation with the same component
47. In the Transform Message properties view, click the Add new target button.

48. In the Selection dialog box, change the output to Variable.


49. Set Variable name to DWoutput.

50. Click OK.


51. Click the drop-down menu for the output; you should see that you can switch between the two
transformations.

52. For the new transformation, set the output type to json and set the expression to payload.

Test the application


53. Save the file to redeploy the project in debug mode.
54. In Advanced REST Client, post the same request to http://localhost:8081/api/flights.
55. In the Mule Debugger, step to the Logger.
56. Review Payload; it should be Java as before.

231
57. Expand Variables; you should see the new DWoutput variable.

58. Step through the rest of the application and switch perspectives.

Review the Transform Message XML code


59. Right-click the Transform Message component and select Go to XML.
60. Locate and review the code for both DataWeave transformations.

61. Switch back to the Message Flow view.

232
Save a DataWeave script to an external file
62. In the Transform Message Properties view, make sure the payload output expression is selected.
63. Click the Edit current target button (the pencil) above the code.

64. In the Selection dialog box, change the source code selection from inline to file.
65. Set the file name to json_flight_playground.

66. Click OK.

Locate and review the code that uses an external DataWeave script
67. Switch to Configuration XML view.
68. Locate the new code for the transformation in postFlight.

233
69. In the Package Explorer, expand src/main/resources.

70. Open json_flight_playground.dwl.


71. Review and then close the file.

72. Return to Message Flow view in implementation.xml.

Change the output type to XML and review errors


73. In the Transform Message properties view, select the Variable – DWoutput output.
74. Change the output type from application/json to application/xml.
75. Locate the warning icons indicating that there is a problem.

Note: If you do not see the warnings, click the Preview button.

76. Mouse over the icon located to the left of the code; you should see a message that there was an
exception trying to output the second root <flightCode>.
77. Click the icon above the code; a List of warnings and errors dialog box should open.

234
78. Select and review the first issue.

79. Click OK.

Note: You will learn how to successfully transform to XML in the next walkthrough.

Test the application


80. Save the file to redeploy the project in debug mode.
81. In Advanced REST Client, post the same request to http://localhost:8081/api/flights.
82. In the Mule Debugger, step once; you should get an error.
83. Review the error information; you should see there is a DataWeave error when trying to output the
second root.

84. Step to the end of the application and switch perspectives.

235
Walkthrough 6-2: Transform basic JSON, Java, and XML
data structures
In this walkthrough, you continue to work with the JSON flight data posted to the flow. You will:

 Write scripts to transform the JSON payload to various JSON and Java structures.
 Write scripts to transform the JSON payload to various XML structures.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Write expressions to transform JSON to various Java structures


1. Return to the Transform Message properties view for the transformation in postFlight.
2. In the output drop-down menu, make sure the payload output expression is selected.
3. Change the output type from java to json.
4. Type a period after payload and double-click price in the auto-completion menu.

236
5. Look at the preview.

Note: Click the Preview button if the preview section is not displayed.

6. Change the output type from json to java.

7. Change the DataWeave expression to data: payload.price.

8. Change the output type from java to json.

9. Change the DataWeave expression to data: payload.

237
10. Change the output type from json to java.

11. Change the DataWeave expression to data: {}.


12. Add a field called hub and set it to “MUA”.

13. Change the output type from java to json.

14. Add a field called code and use auto-completion to set it to the toAirportCode property of the payload.
15. Add a field called airline and set it to the airline property of the payload.

238
Write an expression to output data as XML
16. In the output drop-down menu, select Variable – DWoutput.
17. Change the DataWeave expression to data: payload.
18. Look at the preview; you should now see XML.

Note: Click the Preview button if the preview section is not displayed.

19. In the output drop-down menu, select Payload.


20. Copy the DataWeave expression.
21. Switch back to Variable – DWoutput and replace the DataWeave expression with the one you just
copied.

22. Modify the expression so the code and airline properties are child elements of a new element called
flight.

239
23. Modify the expression so the airline is an attribute of the flight element.

Debug the application


24. In the Logger properties view, set the message to the value of the DWoutput variable.

25. Save the file to redeploy the project in debug mode.


26. In Advanced REST Client, post the same request to http://localhost:8081/api/flights.
27. In the Mule Debugger, step to the Logger; you should see the transformed JSON payload and that the
DWoutput variable has a mime-type of application/xml.

28. Step through the application and switch perspectives.


29. Look at the Logger output in the console; you should see the XML.

240
Walkthrough 6-3: Transform complex data structures with
arrays
In this walkthrough, you create a new flow that allows multiple flights to be posted to it, so you have more
complex data with which to work. You will:

 Create a new flow that receives POST requests of a JSON array of flight objects.
 Transform a JSON array of objects to DataWeave, JSON, and Java.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Create a new flow that receives POST requests of a JSON array of flight objects
1. Return to implementation.xml.
2. Drag out an HTTP Listener from the Mule Palette to the bottom of the canvas.
3. Change the flow name to postMultipleFlights.
4. In the HTTP Listener properties view, set the display name to POST /multipleflights.
5. Ensure the connector configuration is set to the existing HTTP_Listener_config.
6. Set the path to /multipleflights and set the allowed methods to POST.

Note: You are bypassing the APIkit router because a corresponding resource/method pair is not
defined in the API.
241
7. Add a Transform Message component to the flow.
8. In the Transform Message properties view, set the expression to payload.

9. Add a Logger to the flow.

Add input metadata for the transformation


10. In the Transform Message properties view, click Define metadata in the input section.
11. In the Select metadata type dialog box, select flights_json and click Select.

242
12. In the Transform Message Properties view, you should now see metadata for the input.

Preview sample data and sample output


13. In the input section, right-click the payload and select Edit Sample Data to get sample input data.
14. Click the Preview button to get sample output data.

If sample data doesn't automatically appear in the preview section, click the Create required sample
data to execute preview link.

15. Look at the preview section; the sample output should be an array of objects.

243
16. Change the output type to application/dw.

Return values for the first object in the collection


17. Change the DataWeave expression to payload[0].

18. Change the DataWeave expression to payload[0].price.

19. Change the DataWeave expression to payload[0].*price.

244
Return collections of values
20. Change the DataWeave expression to return a collection of all the prices.

21. Change the DataWeave expression to payload.price; you should get the same result.

22. Change the DataWeave expression to return a collection of prices and available seats.

[payload.price, payload.emptySeats]

245
Use the map function to return object collections with different data structures
23. Change the DataWeave expression to payload map $.

24. Change the DataWeave expression to set a property called flight for each object that is equal to its
index value in the collection.

25. Change the DataWeave expression to create a property called destination for each object that is equal
to the value of the toAirportCode field in the payload collection.

246
26. Change the DataWeave expression to dynamically add each of the properties present on the payload
objects.

27. Remove the first flight property assignment.


28. Change the DataWeave expression so the name of each object is flight+index and you get flight0 and
flight1.

247
Use explicit named parameters with the map function
29. Change the map function so that it uses two parameters called object and index and set the field name
to just the index value.

30. Change the DataWeave expression so the name of each object is flight+index and you get flight0 and
flight1.

Note: If you want to test the application, change the output type to application/json and then in
Advanced REST Client, make a request to http://localhost:8081/multipleflights and replace the request
body with JSON from the flights-example.json file.

248
Change the expression to output different data types
31. Change the DataWeave expression output type from application/dw to application/json.

32. Change the output type to application/java.

33. Change the output type to application/xml; you should get issues displayed.

249
34. Click the warning icon above the code, review the issues, then click OK.

35. Change the DataWeave expression to create a root node called flights; you should still get issues.

36. Click the warning icon above the code, review the issues, then click OK.

250
Walkthrough 6-4: Transform to and from XML with
repeated elements
In this walkthrough, you continue to work with the JSON data for multiple flights posted to the flow. You will:

 Transform a JSON array of objects to XML.


 Replace sample data associated with a transformation.
 Transform XML with repeated elements to different data types.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Transform the JSON array of objects to XML


1. Return to the Transform Message properties view for the transformation in postMultipleFlights.
2. Change the expression to map each item in the input array to an XML element.

flights: {(payload map (object,index) -> {


'flight$(index)': object
}
)}

251
3. Look at the preview; the JSON should be transformed to XML successfully.

4. Modify the expression so the flights object has a single property called flight.

Change the input metadata to XML


5. In the input section, right-click the payload and select Clear Metadata.

6. Click the Define metadata link.

252
7. In the Select metadata type dialog box, select flights_xml and click Select.

8. In the Transform Message Properties view, you should now see new metadata for the input.

253
Preview sample data and sample output
9. In the input section, click the x on the payload tab to close it.

10. In the Close Sample Data dialog box, click Close tab and Keep file.

11. Right-click the payload and select Edit Sample Data to get sample input data.
12. Look at the XML sample payload.

13. Look at the sample_data folder in src/test/resources.

254
14. Review the transformation expression; you should see an issue.

Note: You may see more than one issue. If so, only one should be an error, the rest warnings.

15. Look at the error then click OK.

Transform XML with repeated elements to a different XML structure


16. In the input section, click on the Context tab to look at the payload metadata.

255
17. Change the DataWeave expression so that the map is iterating over payload..return.

18. Change the DataWeave expression so that the map is iterating over the repeated return elements of
the input.

19. Change the DataWeave expression to return flight elements with dest and price elements that map to
the corresponding destination and price input values.

Note: If you want to test the application with Advanced REST Client, be sure to change the content-type
header to application/xml and replace the request body with XML from the flights-example.xml file.

256
Change the expression to output different data types
20. Change the output type from application/xml to application/dw.

21. Change the output type to application/json.

22. Change the output type to application/java.

23. In the DataWeave expression, remove the {( )} around the map expression.

257
24. In the DataWeave expression, remove the flight property; you should get an object consisting of an
array of five objects.

258
Walkthrough 6-5: Define and use variables and functions
In this walkthrough, you continue to work with the DataWeave transformation in postMultipleFlights. You will:

 Define and use a global constant.


 Define and use a global variable that is equal to a lambda expression.
 Define and use a lambda expression assigned to a variable as a function.
 Define and use a local variable.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Define and use a global constant


1. Return to the Transform Message properties view for the transformation in postMultipleFlights.
2. Change the output type to application/dw.
3. In the header, define a global variable called numSeats that is equal to 400.

var numSeats = 400

4. In the body, add a totalSeats property that is equal to the numSeats constant.

totalSeats: numSeats

259
5. Look at the preview.

6. Comment out the variable declaration in the header.

//var numSeats = 400

Define and use a global variable that is equal to a lambda expression that maps to a
constant
7. In the header, define a global variable called numSeats that is equal to a lambda expression with an
input parameter x equal to 400.
8. Inside the expression, set numSeats to x.

var numSeats = (x=400) -> x

9. Add parentheses after numSeats in the totalSeats property assignment.

totalSeats: numSeats()

10. Look at the preview.

260
Add a plane property to the output
11. Add a plane property to the DataWeave expression equal to the value of the input planeType values.
12. Look at the values of plane type in the preview.

Define and use a global variable that is that is equal to a lambda expression with input
parameters
13. Comment out the numSeats variable declaration in the header.
14. In the header, define a global variable called numSeats that is equal to a lambda expression with an
input parameter called planeType of type String.

var numSeats = (planeType: String) ->

15. Inside the expression, add an if/else block that checks to see if planeType contains the string 737 and
sets numSeats to 150 or 300 otherwise.

16. Change the totalSeats property assignment to pass the object’s planeType property to numSeats.

totalSeats: numSeats(object.planeType)

17. Force the argument to a String.

totalSeats: numSeats(object.planeType as String)

261
18. Look at the preview; you should see values of 150 and 300.

19. Surround the variable declaration in the header with /* and */ to comment it out.

Define and use a lambda expression assigned to a variable as a function


20. In the header, use the fun keyword to define a function called getNumSeats with a parameter called
planeType of type String.

fun getNumSeats(planeType: String)

21. Copy the if/else expression in the numSeats declaration.


22. Set the getNumSeats function equal to the if/else expression.

fun getNumSeats(planeType: String) =


if (planeType contains('737'))
150
else
300

23. In the body, change the totalSeats property to be equal to the result of the getNumSeats function.

totalSeats: getNumSeats(object.planeType as String)

262
24. Look at the preview.

Create and use a local variable


25. Add a do statement around the definition of the getNumSeats function.

26. At the beginning of the do scope, define a local variable called maxSeats that is equal to the if/else
block.

27. After the if/else block, add a body separator then set the body of the do scope to the maxSeats local
variable.

263
28. Modify the indentation to your liking.

29. Look at the preview.

264
Walkthrough 6-6: Coerce and format strings, numbers, and
dates
In this walkthrough, you continue to work with the XML flights data posted to the postMultipleFlights flow. You
will:

 Coerce data types.


 Format strings, numbers, and dates.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Format a string
1. Return to the Transform Message properties view for the transformation in postMultipleFlights.
2. Use the upper function to return the plane value in uppercase.

3. Coerce the argument to a String.

plane: upper(object.planeType as String)

4. Look at the preview.

265
Coerce a string to a number
5. In the preview, look at the data type of the prices; you should see that they are strings.
6. Change the DataWeave expression to use the as keyword to return the prices as numbers.

price: object.price as Number,

7. Look at the preview.

8. Change the output type from application/dw to application/java.


9. Look at the preview; you should see the prices are now either integer (Integer objects) or non-integer
(Double objects).

Coerce a string to a specific type of number object


10. Change the DataWeave expression to use the class metadata key to coerce the prices to
java.lang.Double objects.

price: object.price as Number {class:"java.lang.Double"},

266
11. Look at the preview; you should see the prices are now all Double objects (non-integers).

12. Change the output type from application/java back to application/dw.

Format a number
13. Remove the coercion of the price to a java.lang.Double.
14. Coerce the price to a String and use the format schema property to format the prices to zero decimal
places.

price: object.price as Number as String {format: "###"},

15. Look at the preview; the prices should now be formatted.

16. Change the DataWeave expression to format the prices to two decimal places.

price: object.price as Number as String {format: "###.##"},

267
17. Look at the preview.

18. Change the DataWeave expression to format the prices to two minimal decimal places.

price: object.price as Number as String {format: "###.00"},

19. Look at the preview; all the prices should now be formatted to two decimal places.

Note: If you are not a Java programmer, you may want to look at the Java documentation for the
DecimalFormatter class to review documentation on DecimalFormat patterns.
https://docs.oracle.com/javase/8/docs/api/java/text/DecimalFormat.html

Coerce a string to a date


20. Add a date field to the return object.

date: object.departureDate

21. Look at the preview; you should see the date property is a String.

22. Change the DataWeave expression to use the as operator to convert departureDate to a date object;
you should get issues displayed.

date: object.departureDate as Date

268
23. Look at the errors then click OK.

24. Look at the format of the dates in the preview.


25. Change the DataWeave expression to use the format schema property to specify the pattern of the
input date strings.

date: object.departureDate as Date {format: "yyyy/MM/dd"}

Note: If you are not a Java programmer, you may want to look at the Java documentation for the
DateTimeFormatter class to review documentation on pattern letters.
https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html

26. Look at the preview; you should see date is now a Date object.

269
Format a date
27. Use the as operator to convert the dates to strings, which can then be formatted.
date: object.departureDate as Date {format: "yyyy/MM/dd"} as String

28. Look at the preview section; the date is again a String – but with a different format.

29. Use the format schema property with any pattern letters and characters to format the date strings.

date: object.departureDate as Date {format: "yyyy/MM/dd"} as String {format:


"MMM dd, yyyy"}

30. Look at the preview; the dates should now be formatted according to the pattern.

270
Walkthrough 6-7: Define and use custom data types
In this walkthrough, you continue to work with the flight JSON posted to the flow. You will:

 Define and use custom data types.


 Transform objects to POJOs.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Define a custom data type


1. Return to the Transform Message properties view for the transformation in postMultipleFlights.
2. Select and cut the string formatting expression for the prices.

3. In the header section of the expression, define a custom data type called Currency.
4. Set it equal to the value you cut.

type Currency = String {format: "###.00"}

271
Use a custom data type
5. In the DataWeave expression, set the price to be of type currency.

price: object.price as Number as Currency,

6. Look at the preview; the prices should still be formatted as strings to two decimal places.

Transform objects to POJOs


7. Open the Flight.java class in the project's src/main/java folder, look at the names of the properties then
close the file.

8. Return to the Transform Message properties view for the transformation in postMultipleFlights.
9. In the header section of the expression, define a custom data type called Flight that is of type
com.mulesoft.training.Flight.

type Flight = Object {class: "com.mulesoft.training.Flight"}

272
10. In the DataWeave expression, set the map objects to be of type Flight.

11. Look at the preview.

Note: Click the Preview button if the preview section is not displayed.

12. Change the output type from application/dw to application/java.

13. Look at the issues you get then click OK.

14. Change the name of the dest key to destination.

destination: object.destination,
273
15. Change the other keys to match the names of the Flight class properties:

 plane to planeType
 date to departureDate

16. Comment out the totalSeats property.


17. Look at the preview.

Note: If you want to test the application with Advanced REST Client, be sure to change the content-type
header to application/xml and replace the request body with XML from the flights-example.xml file.

274
Walkthrough 6-8: Use DataWeave functions
In this walkthrough, you continue to work with the flights JSON posted to the flow. You will:

 Use functions in the Core module that are imported automatically.


 Replace data values using pattern matching.
 Order data, remove duplicate data, and filter data.
 Use a function in another module that you must explicitly import into a script to use.
 Dasherize data.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Use the replace function


1. Return to the Transform Message properties view for the transformation in postMultipleFlights.
2. Change the output type from application/java to application/dw.
3. Look at the preview and see that Boeing is misspelled.

4. For planeType, use the replace function to replace the string Boing with Boeing.

planeType: upper(replace(object.planeType,/(Boing)/) with "Boeing"),

5. Look at the preview; Boeing should now be spelled correctly.

275
Use the dasherize function in the Strings module
6. For planeType, replace the upper function with the dasherize function.

planeType: dasherize(replace(object.planeType,/(Boing)/) with "Boeing"),

7. Look at the error you get then click OK.

8. In the script header, add an import statement to import dasherize from the Strings module.

import dasherize from dw::core::Strings

9. Look at the preview.

276
Use the orderBy function
10. In the preview section, look at the flight prices; the flights are not ordered by price.
11. Add parentheses around the value of the flights root node then use the orderBy function to order the
flights by price.

orderBy $.price

12. Look at the preview; the flights should now be ordered by price.

13. Look at the three $283 flights; there is a duplicate and they are not ordered by date.
14. Change the DataWeave expression to sort flights by date and then by price.

orderBy $.departureDate orderBy $.price

15. Look at the preview; the flights should now be ordered by price and flights of the same price should be
sorted by date.

277
Remove duplicate data
16. Use the distinctBy function to first remove any duplicate objects.
distinctBy $ orderBy $.departureDate
orderBy $.price

17. Look at the preview; you should now see only two $283 flights to PDX instead of three.

18. Add an availableSeats field that is equal to the emptySeats field and coerce it to a number.

availableSeats: object.emptySeats as Number

19. Look at the preview; you should get three $283 flights to PDX again.

278
Use the filter function
20. In the preview, look at the values of the availableSeats properties; you should see one is equal to zero.
21. Use the filter function to remove any objects that have availableSeats equal to 0.

distinctBy $ filter ($.availableSeats !=0)


orderBy $.departureDate orderBy $.price

22. Look at the preview; you should no longer get the flight that had no available seats.

279
Walkthrough 6-9: Look up data by calling a flow
In this walkthrough, you continue to work with the transformation in getMultipleFlights. You will:

 Call a flow from a DataWeave expression.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Create a lookup flow


1. Return to the Transform Message properties view for the transformation in postMultipleFlights.
2. Copy the getNumSeats function.

3. Drag a Transform Message component from the Mule Palette and drop it at the bottom of the canvas to
create a new flow.
4. Change the name of the flow to getTotalSeats.

5. In the Transform Message properties view of the component in getTotalSeats, paste the function you
copied into the script header.

280
6. In the script body, call the function, passing to it the payload's planeType property.
getNumSeats(payload.planeType)

Call a flow from a DataWeave expression


7. Return to the Transform Message properties view for the transformation in postMultipleFlights.
8. Add a property called totalSeats inside the expression (keep the other one commented out).
9. Change the return type of the map function from Flight to Object.

10. Set totalSeats equal to the return value from the DataWeave lookup() function.

totalSeats: lookup()

11. Pass to lookup() an argument that is equal to the name of the flow to call: "getTotalSeats".
12. Pass an object to lookup() as the second argument.

281
13. Give the object a field called planeType (to match what the flow is expecting) and set it equal to the
value of the planeType field.

totalSeats: lookup("getTotalSeats",{planeType: object.planeType})

14. Look at the preview.

Note: Click the Preview button if the preview section is not displayed.

15. Look at the warning you get then click OK.

Test the application


16. Save the file and, if necessary, run or debug the project.
17. In Advanced REST Client, make sure the method is set to POST and the request URL is set to
http://localhost:8081/multipleflights.
18. Set a Content-Type header to application/xml.

282
19. Set the request body to the value contained in the flights-example.xml file in the src/test/resources
folder.

20. Send the request; you should get the DataWeave representation of the return flight data and each flight
should have a totalSeats property equal to 150 or 300.

21. Return to Anypoint Studio.


22. Stop the project.
23. Close the project.

283
Module 7: Triggering flows

At the end of this module, you should be able to:

 Read and write files.


 Trigger flows when files are added, created, or updated.
 Trigger flows when new records are added to a database table.
 Schedule flows to run at a certain time or frequency.
 Persist and share data in flows using the Object Store.
 Publish and consume JMS messages.

284
Walkthrough 7-1: Trigger a flow when a new file is added
to a directory
 In this walkthrough, you load data from a local CSV file when a new file is added to a directory. You will:
 Add and configure a File listener to watch an input directory.
 Restrict the type of file read.
 Rename and move the processed files.

Starting file
If you did not complete walkthrough 2-4, you can get a starting file here. This file is also located in the solutions
folder of the student files ZIP located in the Course Resources.

Locate files and folders


1. In your computer’s file browser, return to the student files for the course.
2. Open the resources folder and locate the accounts.csv file and the input and output folders.

3. Leave this folder open.

Add the File module to the project


4. Return to Anypoint Studio and open the apdev-examples project.
5. Open accounts.xml.
6. In the Mule Palette, select Add Modules.
7. Select the File connector in the right side of the Mule Palette and drag and drop it into the left side.

285
8. If you get a Select module version dialog box, select the latest version and click Add.

Create a flow that monitors a location for new files


9. Locate the On New or Updated File operation for the File connector in the right side of the Mule Palette
and drag and drop it at the top of the canvas to create a new flow.
10. Rename the flow to getCSVaccounts.

Configure the File connector


11. Open global.xml and switch to the Global Elements view.
12. Click Create.
13. In the Choose Global Type dialog box, select Connector Configuration > File Config and click OK.

14. In the Global Element Properties dialog box, select the Connection checkbox then click the browse
button next to Working Directory.

286
15. Browse to the student files folder for the course.
16. Select the resources folder and click Open.

17. Select and cut the value of the working directory that got populated and replace it with a property
${file.accountsDir}.

18. In the Global Element Properties dialog box, click OK.


19. Open config.yaml in src/main/resources.
20. Create a new property file.accountsDir and set it equal to the value you cut.

Note: Users on all OSs, including Windows, should use forward slash characters as shown.

287
Configure the On New or Updated File operation
21. Return to accounts.xml.
22. In the On New or Updated File properties view, change the display name to accounts.csv.
23. Set the connector configuration to the existing File_Config.

24. In the General section, set the directory to input.


25. Set the matcher to Edit inline.
26. Set filename pattern to *.csv.

288
27. In the Post processing action section, set the move to directory to output.

28. In the General section, review the default scheduling information; the endpoint checks for new files
every 1000 milliseconds.

Review event metadata in the DataSense Explorer


29. Select the Output tab in the DataSense Explorer; you should see no metadata about the structure of
the CSV file.

289
Display the file contents
30. Add a Logger to the flow.
31. In the Logger properties view, set the display name to payload and the message to display the payload.

#[payload]

Debug the application


32. Add a breakpoint to the Logger.
33. Save the files and debug the project.
34. In your computer’s file browser, return to the resources folder in student files for the course.
35. Move the accounts.csv file to the input folder.

36. Return to the Mule Debugger and look at the payload.

290
37. Expand Attributes and locate the fileName and path attributes.

38. Step to the end of the application.


39. In your computer’s file browser, return to the student files for the course; you should see accounts.csv
has been moved to the output folder.

40. Return to Anypoint Studio and look at the console; you should see the file contents displayed.

Rename the file


41. Return to the accounts.csv properties view and in the Post processing action section, set the Rename
to property to an expression that appends .backup to the original filename.

#[attributes.fileName ++ ".backup"]

291
Test the application
42. Save the file to redeploy the project.
43. Remove the breakpoint from the Logger.
44. In your computer’s file explorer, move the accounts.csv file from the output folder back to the input
folder; you should see it appear in the output folder with its new name.

45. Move the accounts.csv.backup file from the output folder back to the input folder; it should not be
processed and should stay in the input folder.

46. Return to Anypoint Studio and switch perspectives.


47. Stop the project.

292
Walkthrough 7-2: Trigger a flow when a new record is
added to a database and use automatic watermarking
In this walkthrough, you work with the accounts table in the training database. You will:

 Add and configure a Database listener to check a table on a set frequency for new records.
 Use the listener’s automatic watermarking to track the ID of the latest record retrieved and trigger the
flow whenever a new record is added.
 Output new records to a CSV file.
 Use a form to add a new account to the table and see the CSV file updated.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

View accounts data


1. Return to the course snippets.txt file and copy the text for the MUA Accounts URL.
2. In a web browser, navigate to the MUA accounts by pasting the URL.
3. Review the data and the names of the columns which match those of a database table.

293
Look at the File listener settings for watermarking
4. Return to accounts.xml in Anypoint Studio.
5. Return to the accounts.csv properties view for the listener in getCSVaccounts.
6. Locate the watermark mode setting in the General section and look at its possible values.

Add the Database module to the project


7. In the Mule Palette, select Add Modules.
8. Select the Database connector in the right side of the Mule Palette and drag and drop it into the left
side.
9. If you get a Select module version dialog box, select the latest version and click Add.

Create a flow to monitor a database


10. Locate the On Table Row operation for the Database connector in the right side of the Mule Palette and
drag and drop it at the top of the canvas to create a new flow.
11. Rename the flow to syncDBaccountsToCSV.

294
Configure a Database connector
12. Return to the course snippets.txt file.
13. Locate and copy the MySQL (or Derby) database properties.
14. Return to config.yaml and paste the properties.

Note: The database information you see may be different than what is shown here; the values in the
snippets file differ for instructor-led and self-study training classes.

15. Save the file.


16. Return to global.xml and create a new Database Config that uses these properties.

Note: If necessary, refer to the detailed steps in Walkthrough 4-2 of the Getting Started with Anypoint
Platform course.

17. Add the MySQL (or Derby) JDBC driver.

295
18. Test the connection and make sure it is successful.

Configure the Database listener


19. Return to accounts.xml.
20. In the On Table Row properties view, set the following values:

 Display Name: accounts


 Connector configuration: Database_Config
 Table: accounts
 Watermark column: accountID
 Id column: accountID
 Frequency: 10
 Time unit: SECONDS

296
Write new records to a CSV file
21. Add a File Write operation to the flow.

22. In the Write properties view, set the following values:

 Display Name: DBaccounts.csv


 Connector configuration: File_Config
 Path: output/DBaccounts.csv
 Write mode: APPEND

297
23. Expand Payload in the Input tab in the DataSense Explorer; you should see the operation will get an
account with account information from the Database operation.

Transform the records to CSV


24. Add a Transform Message component before the Write operation.
25. Change the display name to Java to CSV.

26. In the Transform Message properties view, change the output type to application/csv and add a header
property equal to false.
27. Set the body expression to [payload].

Add a Logger to display the records


28. Add a Logger to the end of the flow.
29. Change the Logger display name to payload.
298
30. Set the Logger message to display the payload.

Set the application to prompt to clear application data when it starts


31. Add a breakpoint to the Transform Message component.
32. Save all files then, in the main menu, select Run > Debug Configurations.
33. Select apdev-examples in the left menu bar under Mule Applications.
34. In the Debug Configurations dialog box, locate the Clear Application Data section in the General tab
and change it to Prompt.

Note: You need to rerun or debug an application to get the prompt; you cannot just save to redeploy.

299
Debug the project
35. Click Debug.
36. In the Clear Application Data dialog box, click Yes.

37. After the breakpoint is hit, in the Mule Debugger, expand Payload.

38. Click Resume and step through several of the records.

300
39. Look at the console; you should see the records displayed.

40. Stop the project and switch perspectives.

Clear application data and test the application


41. Run the project.
42. In the Clear Application Data dialog box, click Yes.
43. Look at the console; you should see many records.

44. Stop the project.


45. Return to the resources folder in your computer’s file explorer; you should see a new DBaccounts.csv
file appear in the output folder.

46. Open the DBaccounts.csv file with a text editor; you should see the records.
47. Close the DBaccounts.csv file.

301
Test the application again without clearing application data
48. Return to Anypoint Studio and run the project.
49. In the Clear Application Data dialog box, click No.
50. Look at the console; you should see no new records output (unless someone else just added one!).

Add a new account to the database


51. Return to the MUA Accounts page in the web browser.
52. Click Add account.
53. Fill out the form with data and click Save.

Note: Set the postal code to a specific value. In the next walkthrough, you will retrieve only new records
with this specific postal code, so you do not get all of the records.

54. On the MUA accounts page, locate your new account.

302
55. Return to the console in Anypoint Studio; you should see your new record.

56. Stop the project.


57. Return to your computer’s file explorer; the modified date on the DBAccounts.csv file should have been
updated.
58. Open DBaccounts.csv and locate your new record at the end of the file.

59. Close the DBaccounts.csv file.

303
Walkthrough 7-3: Schedule a flow and use manual
watermarking
In this walkthrough, you continue to work with the accounts table in the training database. You will:

 Use the Scheduler component to create a new flow that executes at a specific frequency.
 Retrieve accounts with a specific postal code from the accounts table.
 Use the Object Store component to store the ID of the latest record and then use it to only retrieve new
records.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Create a flow that executes at a specific frequency


1. Return to accounts.xml in Anypoint Studio.
2. Locate the Scheduler component in the Core section of the Mule Palette.

304
3. Drag a Scheduler component from the Mule Palette and drop it at the top of the canvas to create a new
flow.
4. Change the name of the flow to syncDBaccountsWithPostal.

5. In the Scheduler properties view, set the frequency to 10 seconds.

Retrieve records with a specific postal code from the database


6. From the Mule Palette, drag a Database Select operation and drop it in the flow.

7. In the Select properties view, set the following:

 Display Name: accounts


 Connector configuration: Database_Config
 SQL query text: SELECT * FROM accounts WHERE postal = :postal

305
8. In the Input Parameters section, use expression mode to create a postal input parameter with the
specific postal code you used in the previous walkthrough.

{ postal: 'yourPostalValue'}

Note: If you want, you can store the postal code as a property in config.yaml and then reference it here
in the DataWeave expression as { postal: p('propertyName')}.

Output the records to a CSV file


9. Copy the Write operation in syncDBaccountsToCSV and paste it at the end of
syncDBaccountsWithPostal.

10. In the properties view for the Write operation, set the following values:

 Display Name: DBaccountsPostal.csv


 Path: output/DBaccountsPostal.csv

306
11. Change the content to output the payload as application/csv with a header property equal to false.

output application/csv header=false --- payload

Log the payload


12. Add a Logger at the end of the flow and change the display name to CSV payload.

13. Set the message to the payload as type application/csv.

307
Stop the syncDBaccountsToCSV flow so it does not run
14. In the properties view for the syncDBaccountsToCSV flow, set the initial state to stopped.

Test the application


15. Save the file and run the project.
16. In the Clear Application Data dialog box, click Yes.
17. Watch the console, you should see the same records displayed every 10 seconds.

Note: Right now, all records with matching postal code are retrieved – over and over again. Next, you
will modify this so only new records with the matching postal code are retrieved.

18. Stop the project.


19. Return to the resources folder in your computer’s file browser; you should see the new
DBaccountsPostal.csv file in the output folder.

20. Open the file, review the contents then close the file.
21. Delete the file.

308
Add the ObjectStore module to the project
22. Return to Anypoint Studio and in the Mule Palette, select Add Modules.
23. Select the ObjectStore connector in the right side of the Mule Palette and drag and drop it into the left
side.
24. If you get a Select module version dialog box, select the latest version and click Add.

Store the ID of the last record retrieved


25. Drag the Store operation for the ObjectStore connector from the Mule Palette and drop it after the
Database Select operation.

26. In the Store properties view, set the display name and key to lastAccountID.

309
27. Set the value to an expression for the maximum value of lastAccountID in the payload containing the
retrieved records.

max(payload.*accountID)

Before the query, retrieve the ID of the last record retrieved


28. Drag the Retrieve operation for the ObjectStore connector from the Mule Palette and drop it before the
Database Select operation.

29. In the Retrieve properties view, set the following values:

 Display Name: lastAccountID


 Key: lastAccountID
 Default value: 0

310
30. Select the Advanced tab and set the target variable to lastAccountID so the value is stored in a variable
called lastAccountID.

Modify the query to only retrieve new records with a specific postal code
31. In the accounts Select properties view, add a second query input parameter called lastAccountID that is
equal to the watermark value.

{postal: 'yourValue', lastAccountID: vars.lastAccountID}

32. Modify the SQL query text to use this parameter to only retrieve new records.

SELECT * FROM accounts WHERE postal = :postal AND accountID > :lastAccountID

Only store the value if new records were retrieved


33. Add a Choice router after the Select operation.

34. Move the Store, Write, and Logger operations into the when branch of the router.

311
35. Add a Logger to the default branch.

36. In the default branch Logger properties view, set the display name and message to No new records.

37. In the Choice router, click the when scope and in the properties view, add an expression to route the
event when the payload is not empty.

#[not isEmpty(payload)]

312
Clear the application data and debug the application
38. Add a breakpoint to the Retrieve operation.
39. Save the file and debug the project.
40. In the Clear Application Data dialog box, click Yes.
41. In the Mule Debugger, step to the Select operation; you should see a lastAccountID variable with a
value of 0.

42. Step into the Choice router; you should see record(s) were retrieved from the database.

313
43. Click resume; the flow should be executed again, and execution should be stopped back at the
beginning of the flow.
44. Step to the Select operation; you should see the lastAccountID variable now has a non-zero value.

45. Step into the Choice router; you should see no records were retrieved from the database (unless
someone else just added one with the same postal code!).

46. Stop the project and switch perspectives.


47. Return to your computer’s file explorer and locate and open the new DBaccountsPostal.csv file in the
output folder.

Note: If you see the same records more than once, it was because during debugging, the flow was
executed again before the watermark was stored.

48. Close the DBaccountsPostal.csv file.

314
Debug the application and do not clear application data
49. Return to Anypoint Studio and debug the project.
50. In the Clear Application Data dialog box, click No.
51. In the Mule Debugger, step to the Select operation; you should see a lastAccountID variable with the
same non-zero value.

52. Step into the Choice router; no new records should have been returned.
53. Remove the breakpoint from the Retrieve operation.
54. Make sure there are no other breakpoints in the flow then click Resume to continue application
execution.

Note: If your application still halts at the Retrieve operation, stop then debug the project without clearing
the application data.

Add a new account to the database


55. Return to the MUA Accounts page in the web browser.
56. Click Add account.
57. Fill out the form with data and use the same postal code.

58. Click Save.

315
59. You should see your new account on the MUA accounts page.
60. Return to Anypoint Studio; you should see your new record in the console.

61. Return to your computer’s file explorer; the modified date on the DBAccountsPostal.csv file should have
been updated.
62. Open DBaccountsPostal.csv and locate your new record at the end of the file.
63. Close the DBaccountsPostal.csv file.
64. Return to Anypoint Studio and switch perspectives.
65. Stop the project.

316
Walkthrough 7-4: Publish and listen for JMS messages
In this walkthrough, you send a JMS message for each new database record so it can be processed
asynchronously. You will:

 Add and configure a JMS connector for ActiveMQ (that uses an in-memory broker).
 Send messages to a JMS queue.
 Listen for and process messages from a JMS queue.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Add the JMS module to the project


1. Return to accounts.xml.
2. In the Mule Palette, select Add Modules.
3. Select the JMS connector in the right side of the Mule Palette and drag and drop it into the left side.
4. If you get a Select module version dialog box, select the latest version and click Add.

317
Configure the JMS connector
5. Return to the Global Elements view of global.xml.
6. Click Create.
7. In the Choose Global Type dialog box, select Connector Configuration > JMS Config and click OK.

8. In the Global Element Properties dialog box, make sure the connection is set to ActiveMQ Connection.
9. Click the Configure > Add Maven dependency option for the ActiveMQ Broker.
10. In the Maven dependency dialog box, enter activemq-broker in the Search Maven Central field.
11. Select the org.apache.activemq:activemq-broker in the results that are displayed.
12. Click Edit selected.

318
13. Enter 5.16.5 in the Version text field.
Note: Version 5.16.5 is the latest ActiveMQ driver compatible with Java 8 which is used by the Mule
runtime.

14. Click Finish.

319
15. Scroll down and locate the Connection Factory section.
16. For Factory configuration, select Edit inline; the Broker url should already be populated.

17. Click OK.

Use the JMS Publish operation to send a message to a JMS queue


18. Return to accounts.xml.
19. Drag out a JMS Publish operation from the Mule Palette and drop it after the Write operation in
syncDBaccountsWithPostal.

320
20. In the Publish properties view, set the following values:

 Display Name: JMS accountsQ


 Connector configuration: JMS_Config
 Destination: accountsQ
 Destination type: QUEUE

21. Modify the message body to be of type application/json.


output application/json --- payload

22. Scroll down and locate the User Properties field.


23. Use expression mode and set it equal to an object with a key called publisher and a value of training.

{"publisher":"training"}

321
Create a flow to listen to a JMS topic
24. Drag out the JMS On New Message operation from the Mule Palette and drop it in the canvas to create
a new flow.
25. Give the flow a new name of receiveJMSMessages.

26. In the On New Message properties view, set the following values:

 Display Name: JMS accountsQ


 Connector configuration: JMS_Config
 Destination: accountsQ
 Consumer type: Queue consumer

322
27. Add a Logger to the flow.
28. Set its display name to payload and its message to #[payload].

Clear application data and debug the application


29. Add a breakpoint to the Logger in receiveJMSmessages.
30. Save the files and debug the project.
31. In the Clear Application Data dialog box, click Yes.
32. Wait until the project deploys; application execution should stop in receiveJMSMessages.
33. In the Mule Debugger view, look at the value of the payload.

323
34. Expand the Attributes and locate the publisher property in the userProperties.

35. Step through the rest of the application; you should see the JSON message in the console.

Note: If you want to test further, return to the MUA Accounts in the web browser and add a new record
with the same postal code.

36. Stop the project and switch perspectives.

324
Module 8: Processing records

At the end of this module, you should be able to:

 Process items in a collection using the For Each scope.


 Process records using the Batch Job scope.
 Use filtering and aggregation in a batch step.

325
Walkthrough 8-1: Process items in a collection using the
For Each scope
In this walkthrough, you split a collection and process each item in it. You will:

 Use the For Each scope element to process each item in a collection individually.
 Change the value of an item inside the scope.
 Examine the payload before, during, and after the scope.
 Look at the thread used to process each item.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Stop the syncDBaccountsWithPostal flow so it does not run


1. Return to accounts.xml.
2. In the properties view for the syncDBaccountsWithPostal flow, set the initial state to stopped.

3. Right-click in the canvas and select Collapse All.

Add a For Each scope


4. Expand getCSVaccounts.
5. In the Mule Palette, select Core.

326
6. Locate the For Each scope and drag and drop it before the Logger.

Transform the input to a collection


7. Add a Transform Message component before the For Each scope.
8. Set its display name to CSV to Java.

9. In the Transform Message properties view, leave the output type set to java and set the expression to
payload.

Process each element in the For Each scope


10. Add a Set Payload transformer and a Logger to the For Each scope.

327
11. In the Set Payload properties view, set the display name and value to processed.

12. Set the Logger display name to payload and have it display the payload.

Change the File listener so it does not rename files


13. In the accounts.csv properties view, delete the Rename to value.

Debug the application


14. Add a breakpoint to the Transform Message component.
15. Save the file, debug the project, and do not clear application data.

328
16. Return to the student files in your computer’s file browser.

17. Rename accounts.csv.backup to accounts.csv in the input folder.


18. Return to Anypoint Studio; application execution should have stopped at the Transform Message
component.
19. In the Mule Debugger view, look at the payload type and value.

329
20. Step to the For Each scope; the payload should now be an ArrayList of LinkedHashMaps.

21. Step into the Set Payload in the For Each scope; the payload should now be a LinkedHashMap.
22. Expand Variables; you should see a counter variable.

330
23. Step again; you should see the payload for this record inside the scope has been set to the string,
processed.

24. Step again and look at the payload and counter for the second record.

331
25. Step through the application to the Logger after the For Each scope; the payload should be equal to the
original ArrayList of LinkedHashMaps and not a list of processed strings.

26. Step to the end of the application.


27. Stop the project and switch perspectives.

Look at the processing threads


28. In the console, locate the thread number used to process each item in the collection; the same thread
should be used for each: cpuIntensive.01 in the following screenshot.

332
Walkthrough 8-2: Process records using the Batch Job
scope
In this walkthrough, you create a batch job to process the records in a CSV file. You will:

 Use the Batch Job scope to process items in a collection.


 Examine the payload as it moves through the batch job.
 Explore variable persistence across batch steps and phases.
 Examine the payload that contains information about the job in the On Complete phase.
 Look at the threads used to process the records in each step.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Create a new flow to read CSV files


1. Return to accounts.xml.
2. Drag a Flow scope from the Mule Palette and drop it above getCSVaccounts.
3. Change the flow name to batchProcessCSVaccounts.
4. Select the On New or Updated File operation in getCSVaccounts and copy it.
5. Click the Source section of batchProcessCSVaccounts and paste it.
6. Add a Transform Message component to the flow.
7. Set the display name to CSV to Java.

333
8. In the Transform Message properties view, change the body expression to payload.

Add a Batch Job scope


9. In the Mule Palette, select Core and locate the Batch elements.

10. Drag a Batch Job scope and drop it after the Transform Message component.

Set a variable before the Batch Job scope


11. Add a Set Variable transformer before the Batch Job scope.

12. In the Set Variable properties view, set the following:

 Display Name: size


 Name: size
 Value: #[sizeOf(payload)]
334
Set a variable inside the Batch Job scope
13. Add a Set Variable transformer to the processors phase of the batch step.
14. Add a Logger component after the Set Variable transformer.

15. In the Set Variable properties view, set the following:

 Display Name: cname


 Name: cname
 Value: #[payload.Name]

Create a second batch step


16. Drag a Batch Step scope from the Mule Palette and drop it in the process records phase of the Batch
Job scope after the first batch step.
17. Add a Logger to the processors phase of the second batch step.
18. Add a Logger to the On Complete phase.

Stop the other flow watching the same file directory from being executed
19. In the properties view for the getCSVaccounts flow, set the initial state to stopped.

335
Debug the application
20. In batchProcessCSVaccounts, add a breakpoint to the Transform Message component.
21. Save the file, debug the project, and do not clear application data.
22. Return to the student files in your computer’s file browser and move accounts.csv from the output folder
to the input folder.
23. In the Mule Debugger view, watch the payload as you step to the Batch Job scope; it should go from
CSV to an ArrayList.
24. In the Mule Debugger view, expand Variables; you should see the size variable.

25. Step to the Logger in the first batch step.


26. In the Mule Debugger view, look at the value of the payload; it should be a HashMap.

336
27. Expand Variables; you should see the size variable and the cname variable specific for that record.

28. Step through the rest of the records in the first batch step and watch the payload and the cname
variable change.

337
29. Step into the second batch step and look at the payload and the cname variable; you should see the
cname variable is defined and has a value.

30. Step through the rest of the records in the second batch step and watch the value of cname.
31. Step into the On Complete phase; you should see the payload is an ImmutableBatchJobResult.

338
32. Expand the payload and locate the values for totalRecords, successfulRecords, and failedRecords.

33. Step through the rest of the application and switch perspectives.
34. Stop the project.

Look at the processing threads


35. In the console, locate the thread number used to process each record in the collection in each step of
the batch process; you should see more than one thread used.

339
Walkthrough 8-3: Use filtering and aggregation in a batch
step
In this walkthrough, you use a batch job to synchronize account database records to Salesforce. You will:

 Use a batch job to synchronize database records (with your postal code) to Salesforce.
 In a first batch step, check to see if the record already exists in Salesforce.
 In a second batch step, add the record to Salesforce.
 Use a batch step filter so the second batch step is only executed for specific records.
 Use a Batch Aggregator scope to commit records in batches.

Starting file
If you did not complete the previous walkthrough, you can get a starting file here. This file is also located in the
solutions folder of the student files ZIP located in the Course Resources.

Look at existing Salesforce account data


1. In a web browser, navigate to http://login.salesforce.com/ and log in with your Salesforce Developer
account.
2. Click the App Launcher, click View All, then click the Accounts link.

3. In the view drop-down menu, select All Accounts.

340
4. Look at the existing account data; a Salesforce Developer account is populated with some sample data.

5. Notice that countries and postal codes are not displayed by default.
6. In the List View Controls drop-down menu, select New.

7. In the New List View dialog box, set the list name to All Accounts with Postal Code.
8. Select All users can see this list view.

9. Click Save.

341
10. In the List View Controls drop-down menu, select Select Fields to Display.

11. In the Select Fields to Display dialog box, select Billing Zip/Postal Code as the available field and click
the Move selection to Visible Fields button.
12. Select Billing Country as the available field and click the Move selection to Visible Fields button.
13. Use the Up and Down buttons to order the fields as you prefer.

14. Click Save; you should now see all the accounts with postal codes and countries.
15. Adjust the column widths as you prefer.

342
Add an account to Salesforce with a name matching one of the database records
16. Click the New button.

17. In the New Account dialog box, enter an account name (one that matches one of the accounts you
added with your postal code to the database) and click Save.

18. Leave this browser tab open.

Add a Batch Job scope to the receiveJMSmessages flow


19. Return to accounts.xml in Anypoint Studio.
20. Drag a Batch Job scope from the Mule Palette and drop it before the Logger in the
receiveJMSmessages flow.

343
21. Change the display name of the batch job to syncWithSalesforce.

Query Salesforce to see if an account already exists


22. Change the name of the batch step inside the batch job to isAccountInSalesforce.
23. Drag a Salesforce Query operation from the Mule Palette and drop it in the processors phase in the
batch step.

24. In the Query properties view, set the following values:

 Display Name: Account


 Connector configuration: Salesforce_Config
 Salesforce query: SELECT Name FROM Account

Note: You will add to this query shortly.

344
Transform the input JSON data to Salesforce Account objects
25. Add a Transform Message component before the Batch Job.
26. Change the display name to JSON to Accounts.

27. In the Transform Message properties view, look at the metadata in the input section.
28. Right-click Payload and select Set Metadata.

345
29. Create a new metadata type with the following information:

 Type id: accounts_json


 Type: JSON
 Example: Use the accounts.json file in the resources/examples folder of the student files

30. In the Transform Message properties view, click the Show Graphics button and map the following
fields:

 name: Name
 street: BillingStreet
 city: BillingCity
 state: BillingState
 postal: BillingPostalCode
 country: BillingCountry

Note: If you do not get Salesforce metadata for the Account object, you can copy the DataWeave
transformation from the course snippets.txt file.

346
Finish the batch step to check if an account already exists in Salesforce
31. In the Query properties view, add an input parameter named cname.
32. Set the parameter value to payload.Name, ensure it is a String, and give it a default value.

payload.Name default "" as String

33. Modify the Salesforce query to look for accounts with this name.
SELECT Name FROM Account
WHERE Name= ':cname'

Store the result in a variable instead of overriding the payload


34. Select the Advanced tab.
35. Set the target variable to exists.
36. Set the target value to

#[(sizeOf(payload as Array) > 0)]

347
37. Add a Logger after the Query operation.
38. Add a Logger to the On Complete phase.

Change the initial state of the flow


39. In the properties view for the syncDBaccountsWithPostal flow, change the initial state to started.

Debug the application


40. In the receiveJMSmessages flow, add a breakpoint to the Transform Message component before the
batch job.
41. Save the file and debug the project.
42. Clear the application data.
43. In the Mule Debugger, wait until application execution stops in the receiveJMSmessages flow.

348
44. Step to the Logger in the first batch step and expand Variables; you should see the exists variable set
to true or false.

45. Step through the application; you should see the exists variable set to false for records with names that
don’t exist in Salesforce and true for those that do.
46. Stop the project and switch perspectives.

Set a filter for the insertion step


47. Add a second batch step to the batch job.
48. Change its display name to writeToSalesforce.

349
49. In the properties view for the second batch step, set the accept expression so that only records that
have the variable exists set to false are processed.

#[not vars.exists]

Use the Salesforce Create operation to add new account records to Salesforce
50. Add Salesforce Create operation to the second batch step in the processors phase.

51. In the Create properties view, set the following:

 Display Name: Accounts


 Connector configuration: Salesforce_Config
 Type: Account
 Records: payload

350
52. Select the Input tab in the DataSense Explorer; you should see this operation expects an Array of
Account objects – not just one.

Create the Array of objects that the operation is expecting


53. Drag a Batch Aggregator scope from the Mule Palette and drop it in the aggregator phase of the
second batch step.
54. Move the Salesforce Create operation into the Batch Aggregator.

55. In the Batch Aggregator properties view, set the aggregator size to 3.

351
56. Add a Logger after the Create operation.

Test the application


57. Save the file, debug the project, and clear the application data.
58. Step through the application until you step into the Batch Aggregator.
59. Expand Payload.

352
60. Step through the rest of the flow.
61. Return to Salesforce and look at the accounts; you should see the records from the legacy MySQL
database are now in Salesforce.

Note: You could also check for the records by making a request to http://localhost:8081/sfdc.

62. Stop the application then run it again but do not clear the application data; no records should be
processed.
63. Return to salesforce.com and locate your new record(s); they should have been inserted only once.
64. Return to Anypoint Studio and stop the project.

353

You might also like