APDevFundamentals Studentmanual
APDevFundamentals Studentmanual
APDevFundamentals Studentmanual
Development:
Fundamentals
Student Manual
1
Table of Contents
INTRODUCING THE COURSE ................................................................................................ 4
Walkthrough: Set up your computer for class ................................................................................................. 5
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
3
Introducing the course
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.
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.
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.
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.
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.
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
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.
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.
Add a Logger
17. Drag a Logger component from the Mule Palette and drop it at the end of the flow.
20. Select the Output tab and examine Payload, Attributes, and HttpRequestAttributes.
16
23. Select the Output tab and examine Payload and Attributes.
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.
17
32. Review the event attributes.
18
37. Locate the query parameters in the logged event data.
19
Walkthrough 1-2: Debug a Mule application
In this walkthrough, you debug and step through the code in a Mule application. You will:
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.
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.
22
14. Expand queryParams and review the values.
23
16. Look at the new value of the payload; it should be Hello.
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.
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.
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:
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.
28
6. Set the display name to GET /goodbye.
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.
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.
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.
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.
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:
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.
35
4. In the Response section, locate the expression that sets the response body by default to the value of
the payload.
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.
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.
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:
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.
#['Goodbye']
39
5. In Advanced REST Client, send the same request; you should get the same result of Goodbye as
before.
#[upper('Goodbye')]
40
15. Type # in the message field and double-click #[payload] in the auto-completion menu.
Message: #[payload]
41
26. Add \n in front of the message to display it on a new line.
#[attributes.queryParams]
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.
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.
43
49. Change the value of fullName to the value of the fname query parameter.
44
57. In Advanced REST Client, send the same request; you should now see the default value Maxine
displayed.
attributes.queryParams.fname
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.
46
Walkthrough 1-6: Set and get variables
In this walkthrough, you create variables associated with an event. You will:
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.
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.
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.
50
Module 2: Structuring Mule
applications
51
Walkthrough 2-1: Create and reference subflows and
private flows
In this walkthrough, you continue to work with apdev-examples.xml. You will:
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.
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.
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.
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:
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.
57
4. In the Package Explorer, locate the JAR file for the VM connector.
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.
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.
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.
61
22. Look at the payload, attributes, and variables.
25. Step through the flow until the event returns to helloFlow.
62
26. Look at the payload, attributes, and variables.
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.
64
37. Look at the value of the payload.
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.
66
7. Set the path to /sfdc and the allowed methods to GET.
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.
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.
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.
69
22. Switch to the Global Elements view; you should see the three configurations.
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.
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:
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.
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.
76
11. Change the port from 8081 to the application property, ${http.port}.
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.
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:
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.
81
12. Ensure the Download RAML from Design Center tab is selected.
14. Sign into Anypoint Platform if prompted, then, in the Browse Design Center for APIs dialog box, select
MUA Flights API and click OK.
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.
83
23. Review its contents and then close the file.
24. Locate pom.xml in the project and open it.
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.
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.
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.
86
Review src/test folders
52. In the project, locate the three src/test folders.
53. Expand the src/test/resources folder.
87
59. In the Export Mule Project dialog box, set the JAR file to a location that you can find and click Finish.
88
Walkthrough 2-6: Manage metadata for a project
In this walkthrough, you define metadata for the apdev-flights-ws project. You will:
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.
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.
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.
91
15. In the Create new type dialog box, set the type id to flights_json.
19. Click the browse button and select the flights-example.json file in src/test/resources.
92
21. In the Apply changes dialog box, click Yes.
93
28. Select Example and browse to and select the flight-example.json 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.
96
Module 3: Consuming web
services
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:
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.
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.
100
16. Set the path to /american.
17. Set the allowed methods to GET.
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.
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}
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.
104
Review metadata associated with the operation
41. Select the output tab in the DataSense Explorer and expand Payload.
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.
106
48. Locate the return type for the get method of the /flights resource.
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.
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.
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:
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.
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.
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.
Name: HTTP_Request_config_training
Base Path: ${training.basepath}
Host: ${training.host}
Port: ${training.port}
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.
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.
114
35. Navigate to the Get flights Request properties view in getUnitedFlights.
36. In the Request section, change the path to /united/flights/{dest}.
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.
116
47. In the Get flights properties view, select the Metadata tab.
48. Click the Add metadata 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.
118
Walkthrough 3-3: Consume a SOAP web service
In this walkthrough, you consume a Delta SOAP web service. You will:
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.
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.
120
13. If you get a Select module version dialog box, select the latest version and click Add.
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.
121
19. In the Choose Global Type dialog box, select Connector Configuration > Web Service Consumer
Config.
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.
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.
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.
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.
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:
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.
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.
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.
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.
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
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:
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.
139
Browse the flow control elements in the Mule Palette
7. In the Core section of the Mule Palette, locate the Flow Control elements.
140
Review the metadata for the Scatter-Gather output
14. In the Logger properties view, explore the input payload structure in the DataSense Explorer.
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.
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.
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:
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.
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.
147
13. For the Flow Reference in the default branch, set the flow name and display name to
getAllAirlineFlights.
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
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.
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.
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.
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).
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:
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.
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.
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.
Note: You can copy this expression from the course snippets.txt file.
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.
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.
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.
163
30. In the Mule Debugger, attempt to step past the validator; you should now get an error.
Note: You will catch this error and send a JSON response with a different status code in the next
module.
164
Module 5: Handling 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.
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.
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.
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.
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).
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.
32. Change the output type of the error response to application/json and display the error.errorType.
170
33. Set the error response status code to 400.
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.
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.
173
Walkthrough 5-2: Handle errors at the application level
In this walkthrough, you create a default error handler for the application. You will:
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.
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.
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.
14. In the Global Element Properties dialog box, set the default error handler to globalError_Handler and
click OK.
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.
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.
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.
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
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.
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:
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.
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.
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.
187
Walkthrough 5-4: Handle errors at the flow level
In this walkthrough, you add multiple error handlers to a flow. You will:
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.
188
4. Set the error type to ANY so it will initially catch both the validation and American flights errors.
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.
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.
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.
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.
193
40. Set the display name and name to httpStatus and set the value to 400.
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.
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.
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:
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.
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.
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.
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.
202
30. Expand Payload; you should now see the three flights and no error messages.
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:
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.
204
7. Set the identifier to INVALID_DESTINATION.
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.
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.
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.
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:
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.
210
3. Review the error handling section in mua-flights-api-main.
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.
11. In the Global Element Properties dialog box, locate the HTTP status var name setting; you should see
httpStatus.
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.
213
20. In the Flow Reference properties view, set the flow name and display name to getFlights.
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.
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.
217
41. Step again; you should see the error is handled by the APIKIT:BAD_REQUEST handler.
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.
218
48. Locate the error handler in the getAmericanFlights flow.
219
Change the global default error scopes to On Error Continue
53. Return to global.xml.
54. Review the types of error handler 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.
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.
222
Walkthrough 5-8: Set a reconnection strategy for a
connector
In this walkthrough, you will:
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.
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
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.
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.
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.
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.
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.
230
Create a second transformation with the same component
47. In the Transform Message properties view, click the Add new target button.
52. For the new transformation, set the output type to json and set the expression to payload.
231
57. Expand Variables; you should see the new DWoutput variable.
58. Step through the rest of the application and switch perspectives.
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.
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.
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.
Note: You will learn how to successfully transform to XML in the next walkthrough.
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.
236
5. Look at the preview.
Note: Click the Preview button if the preview section is not displayed.
237
10. Change the output type from json to java.
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.
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.
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.
242
12. In the Transform Message Properties view, you should now see metadata for the input.
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.
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.
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.
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:
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.
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.
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.
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.
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.
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:
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.
4. In the body, add a totalSeats property that is equal to the numSeats constant.
totalSeats: numSeats
259
5. Look at the preview.
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.
totalSeats: numSeats()
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.
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)
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.
23. In the body, change the totalSeats property to be equal to the result of the getNumSeats function.
262
24. Look at the preview.
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.
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:
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.
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.
266
11. Look at the preview; you should see the prices are now all Double objects (non-integers).
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.
16. Change the DataWeave expression to format the prices to two decimal places.
267
17. Look at the preview.
18. Change the DataWeave expression to format the prices to two minimal decimal places.
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
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.
268
23. Look at the errors then click OK.
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.
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:
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.
3. In the header section of the expression, define a custom data type called Currency.
4. Set it equal to the value you cut.
271
Use a custom data type
5. In the DataWeave expression, set the price to be of type currency.
6. Look at the preview; the prices should still be formatted as strings to two decimal places.
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.
272
10. In the DataWeave expression, set the map objects to be of type Flight.
Note: Click the Preview button if the preview section is not displayed.
destination: object.destination,
273
15. Change the other keys to match the names of the Flight class properties:
plane to planeType
date to departureDate
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:
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.
4. For planeType, use the replace function to replace the string Boing with Boeing.
275
Use the dasherize function in the Strings module
6. For planeType, replace the upper function with the dasherize function.
8. In the script header, add an import statement to import dasherize from the Strings module.
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.
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.
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.
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:
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.
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)
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.
Note: Click the Preview button if the preview section is not displayed.
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.
283
Module 7: Triggering flows
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.
285
8. If you get a Select module version dialog box, select the latest version and click Add.
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}.
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.
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.
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]
290
37. Expand Attributes and locate the fileName and path attributes.
40. Return to Anypoint Studio and look at the console; you should see the file contents displayed.
#[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.
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.
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.
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.
Note: If necessary, refer to the detailed steps in Walkthrough 4-2 of the Getting Started with Anypoint
Platform course.
295
18. Test the connection and make sure it is successful.
296
Write new records to a CSV file
21. Add a File Write operation to the flow.
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.
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].
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.
300
39. Look at the console; you should see the records displayed.
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!).
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.
302
55. Return to the console in Anypoint Studio; you should see your new record.
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.
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.
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')}.
10. In the properties view for the Write operation, set the following values:
306
11. Change the content to output the payload as application/csv with a header property equal to false.
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.
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.
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.
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)
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.
32. Modify the SQL query text to use this parameter to only retrieve new records.
SELECT * FROM accounts WHERE postal = :postal AND accountID > :lastAccountID
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!).
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.
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.
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.
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.
319
15. Scroll down and locate the Connection Factory section.
16. For Factory configuration, select Edit inline; the Broker url should already be populated.
320
20. In the Publish properties view, set the following values:
{"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:
322
27. Add a Logger to the flow.
28. Set its display name to payload and its message to #[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.
324
Module 8: Processing records
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.
326
6. Locate the For Each scope and drag and drop it before the Logger.
9. In the Transform Message properties view, leave the output type set to java and set the expression to
payload.
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.
328
16. Return to the student files in your computer’s file browser.
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.
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:
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.
333
8. In the Transform Message properties view, change the body expression to payload.
10. Drag a Batch Job scope and drop it after the Transform Message component.
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.
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.
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.
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.
343
21. Change the display name of the batch job to syncWithSalesforce.
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:
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.
33. Modify the Salesforce query to look for accounts with this name.
SELECT Name FROM Account
WHERE Name= ':cname'
347
37. Add a Logger after the Query operation.
38. Add a Logger to the On Complete phase.
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.
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.
350
52. Select the Input tab in the DataSense Explorer; you should see this operation expects an Array of
Account objects – not just one.
55. In the Batch Aggregator properties view, set the aggregator size to 3.
351
56. Add a Logger after the Create operation.
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