Tooling Tutorials
Tooling Tutorials
Abstract
Chapter 1. About the Fuse Tooling Tutorials
The Red Hat Fuse Tooling tutorials provide a hands-on introduction to using the Fuse Tooling to develop, run, test, and deploy an Apache Camel application.
Prerequisites
Before you begin, you should be familiar with the following software:
Overview of the Fuse Tooling tutorials
Here is a summary of the tutorials and what you accomplish in each one:
Chapter 2, Setting up your environment
Create a Fuse Integration project and set up the tutorial resource files (example messages and routing context files). When you create a project, it auto-creates a routing context and a preliminary route.
Define the endpoints for a simple route that retrieves messages from a folder and copies them to another folder.
View the test messages. Run the route and verify that it works by seeing that the test messages were copied from the source folder to the target folder.
Chapter 5, Adding a Content-Based Router
Add a content-based router that filters the messages and copies them to different target folders based on content in the messages.
Chapter 6, Adding another route to the routing context
Add another route that further filters the messages and copies them to different target folders based on content in the messages.
Chapter 7, Debugging a routing context
Use the Camel debugger to set breakpoints and then step through a route to examine route and message variables.
Chapter 8, Tracing a message through a route
Drop messages onto the route and track them through all route nodes.
Chapter 9, Testing a route with JUnit
Create a JUnit test case for the route and then test the route.
Chapter 10, Publishing your project to Red Hat Fuse
Walk through the process of publishing an Apache Camel project to Red Hat Fuse: define a local server, configure publishing options, start the server, publish the project, connect to the server, and verify that the project was successfully built and published.
For more details on Fuse Tooling features, see the Tooling User Guide.
About the sample application
The sample application that you build in the Fuse Tooling tutorials simulates a simple order application for zoos to order animals. Sample XML messages are provided - each XML message includes customer information (the name, city, and country of the zoo) and order information (the type and number of animals requested, and the maximum number of animals allowed).
Using the Fuse Tooling, you create a Blueprint project that takes incoming sample messages, filters them based on their content (valid versus invalid orders), and then further sorts the valid orders by the location (country) of the zoo. In the later tutorials, you use the sample application to debug a routing context, trace a message through a route, test a route with JUnit, and finally to publish a Fuse project.
About the resource files
Each tutorial builds upon the previous one. The code generated by one tutorial is the starting point for the next tutorial so that you can complete the tutorials in sequence. Alternately, after you complete the first tutorial, you can do any other tutorial out of sequence by using one of the provided context files as a starting point.
The tutorials rely on resource files provided in the Fuse-tooling-tutorials-jbds-10.3.zip
file located here. This zip file contains two folders:
- Messages
-
This folder contains six message files named
message1.xml
,message2.xml
, … ,message6.xml
. In the first tutorial, Chapter 2, Setting up your environment, you create the directory in which to store these message files and you also view their contents. You need these message files for all tutorials. - blueprintContexts
This folder contains three routing context files:
Blueprint1.xml
- This is the solution routing context resulting from completing the Chapter 3, Defining a Route tutorial. You can use it as the starting point for the following tutorials:-
Blueprint2.xml
- This is the solution context file for the Chapter 5, Adding a Content-Based Router tutorial. You can useblueprint2.xml
as the starting point for the Chapter 6, Adding another route to the routing context tutorial. Blueprint3.xml
- This is the solution context file for the Chapter 6, Adding another route to the routing context tutorial. You can useblueprint3.xml
as the starting point for these tutorials:
Chapter 2. Setting up your environment
This tutorial walks you through the process of creating a Fuse Integration project. The project includes an initial route and a default CamelContext. A route is a chain of processors through which a message travels. A CamelContext is a single routing rule base that defines the context for configuring routes, and specifies the policies to use during message exchanges between endpoints (message sources and targets).
You must complete this tutorial before you follow any of the other tutorials.
Goals
In this tutorial you complete the following tasks:
- Create a Fuse Integration project
- Download test messages (XML files) for your project
- View the test messages
Before your begin
Before you can set up a Fuse Integration project, you must install Red Hat CodeReady Studio with Fuse Tooling. For information on how to install CodeReady Studio, go to the Red Hat customer portal for the installation guide for your platform.
Before you can follow the steps in the Chapter 10, Publishing your project to Red Hat Fuse tutorial, you must install Java 8.
Creating a Fuse Integration project
Open Red Hat CodeReady Studio.
When you start CodeReady Studio for the first time, it opens in the JBoss perspective:
Otherwise, it opens in the perspective that you were using in your previous CodeReady Studio session.
From the menu , select File → New → Fuse Integration Project to open the New Fuse Integration Project wizard:
In the Project Name field, enter
ZooOrderApp
.Leave the Use default workspace location option checked.
Click Next to open the Select a Target Runtime page:
- Select Standalone for the deployment platform.
Choose Karaf/Fuse on Karaf and accept None selected for the runtime.
NoteYou add the runtime later in the Chapter 10, Publishing your project to Red Hat Fuse tutorial .
Accept the default Apache Camel version.
Click Next to open the Advanced Project Setup page, and then select the Empty - Blueprint DSL template:
Click Finish.
Fuse Tooling starts downloading-from the Maven repository-all of the files that it needs to build the project, and then it adds the new project to the Project Explorer view.
If CodeReady Studio is not already showing the Fuse Integration perspective, it asks whether you want to switch to it now:
Click Yes.
The new ZooOrderApp project opens in the Fuse Integration perspective:
The ZooOrderApp project contains all of the files that you need to create and run routes, including:
ZooOrderApp/pom.xml
— A Maven project file.-
ZooOrderApp/src/main/resources/OSGI-INF/blueprint/blueprint.xml
— A Blueprint XML file that contains a Camel routing context and an initial empty route.
To view the preliminary routing context, open the
blueprint.xml
file in the Editor view, and then click the Source tab.
Setting component labels to display ID values
To ensure that the labels of the patterns and components that you place on the Design canvas are the same as the labels shown in the Tooling Tutorials:
Open the Editor preferences page:
- On Linux and Windows machines, select Windows → Preferences → Fuse Tooling → Editor.
- On OS X, select CodeReady Studio → Preferences → Fuse Tooling → Editor.
Check the Use ID values for all component labels option.
- Click Apply and Close.
Downloading test messages for your project
Sample XML message files are provided so that you can test your ZooOrderApp project as you work through the Tooling Tutorials. The messages contain order information for zoo animals. For example, an order of five wombats for the Chicago zoo.
To download and copy the provided test messages (XML files) to your project:
In the CodeReady Studio Project Explorer view, create a folder to contain the test messages:
-
Right-click the
ZooOrderApp/src
folder and then select New → Folder. The New Folder wizard opens. -
For Folder name, type
data
. - Click Finish.
-
Right-click the
Click here to open a web browser to the location of the provided Tooling Tutorial resource
Fuse-tooling-tutorials-jbds-10.3.zip
file.Download the
Fuse-tooling-tutorials-jbds-10.3.zip
file to a convenient location that is external to the ZooOrderApp project’s workspace, and then unzip it. It contains two folders as described in Chapter 1, About the Fuse Tooling Tutorials.From the messages folder, copy the six XML files to your ZooOrderApp project’s
src/data
folder.NoteYou can safely ignore the on the XML files.
Viewing the test messages
Each XML message file contains an order from a zoo (a customer) for a quantity of animals. For example, the 'message1.xml' file contains an order from the Brooklyn Zoo for 12 wombats.
You can open any of the message XML files in the Editor view to examine the contents.
- In the Project Explorer view, right-click a message file.
- From the popup menu, select Open.
Click the Source tab.
The XML file opens in the Editor view.
For example, the contents of the
message1.xml
file shows an order from the Bronx Zoo for 12 wombats:<?xml version="1.0" encoding="UTF-8"?> <order> <customer> <name>Bronx Zoo</name> <city>Bronx NY</city> <country>USA</country> </customer> <orderline> <animal>wombat</animal> <quantity>12</quantity> </orderline> </order>
You can safely ignore the
on the first line of the newly created message1.xml
file, which advises you that there are no grammar constraints (DTD or XML Schema) referenced by the document.
The following table provides a summary of the contents of all six message files:
msg# | <name> | <city> | <country> | <animal> | <quantity> |
---|---|---|---|---|---|
1 | Bronx Zoo | Bronx NY | USA | wombat | 12 |
2 | San Diego Zoo | San Diego CA | USA | giraffe | 3 |
3 | Sea Life Centre | Munich | Germany | penguin | 15 |
4 | Berlin Zoo | Berlin | Germany | emu | 6 |
5 | Philadelphia Zoo | Philapelphia PA | USA | giraffe | 2 |
6 | St Louis Zoo | St Loius MO | USA | penguin | 10 |
Next steps
Now that you have set up your CodeReady Studio project, you can continue to the Chapter 3, Defining a Route tutorial in which you define the route that processes the XML messages.
Chapter 3. Defining a Route
This tutorial walks you through adding and configuring endpoints to a route. Endpoints define the source and sink for messages traveling through the route. For your ZooOrderApp
project, the starting (source) endpoint is the folder containing the XML message files. The sink (finishing) endpoint is another folder that you specify in your project.
Goals
In this tutorial you complete the following tasks:
- Add source and sink endpoints to the route
- Configure the endpoints
- Connect the endpoints
Before you begin
Before you start this tutorial:
- You must set up your workspace environment, as described in the Chapter 2, Setting up your environment tutorial.
-
In CodeReady Studio, open your
ZooOrderApp
project’s/src/main/resources/OSGI-INF/blueprint/blueprint.xml
file in the Editor view. -
If needed, click the Design tab at the bottom of the Editor view to see the graphic display of the initial route, labeled
Route_route1
.
Configuring the source endpoint
Follow these steps to configure the src/data
folder as the route’s source endpoint:
Drag a File component ( ) from the Palette's Components drawer to the canvas, and drop it in the
Route_route1
container node.The File component changes to a
From _from1
node inside theRoute_route1
container node.On the canvas, select the
From _from1
node.The Properties view, located below the canvas, displays the node’s property fields for editing.
To specify the source directory for the message files, in the Properties view, click the Advanced tab:
In the Directory Name field, enter
src/data
:The path
src/data
is relative to the project’s directory.On the Consumer tab, enable the Noop option by clicking its check box.
The Noop option prevents the
message#.xml
files from being deleted from thesrc/data
folder, and it enables idempotency to ensure that eachmessage#.xml
file is consumed only once.Select the Details tab to open the file node’s Details page.
Notice that the tooling automatically populates the Uri field with the Directory Name and Noop properties you configured on the Advanced tab. It also populates the Id field with an autogenerated ID (
_from1
):NoteThe tooling prefixes autogenerated ID values with an underscore (_). You can optionally change the ID value. The underscore prefix is not a requirement.
Leave the autogenerated Id as is.
- Select File → Save to save the route.
Configuring the sink endpoint
To add and configure the route’s sink (target) endpoint:
Drag another File component from the Palette's Components drawer and drop it in the
Route_route1
container node.The File component changes to a
To_to1
node inside theRoute_route1
container node.On the canvas, select the
To_to1
node.The Properties view, located below the canvas, displays the node’s property fields for editing.
On the Details tab:
-
In the Uri field, type
file:target/messages/received
. In the Id field, type
_Received
.NoteThe tooling will create the
target/messages/received
folder at runtime.
-
In the Uri field, type
In the
Route_route1
container, select the From _from1 node and drag its connector arrow ( ) over the To_Received node, and then release it:NoteThe two file nodes are connected and aligned on the canvas according to the route editor’s layout direction preference setting. The choices are Down (the default) and Right.
To access the route editor 's layout preference options:
- On Linux and Windows machines, select Windows → Preferences → Fuse Tooling → Editor → Choose the layout direction for the diagram editor.
- On OS X, select CodeReady Studio → Preferences → Fuse Tooling → Editor → Choose the layout direction for the diagram editor.
NoteIf you do not connect the nodes before you close the project, the tooling automatically connects them when you reopen it.
- Save the route.
Click the Source tab at the bottom of the canvas to display the XML for the route:
<?xml version="1.0" encoding="UTF-8"?> <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd"> <camelContext id="_context1" xmlns="http://camel.apache.org/schema/blueprint"> <route id="_route1"> <from id="_from1" uri="file:src/data?noop=true"/> <to id="_Received" uri="file:target/messages/received"/> </route> </camelContext> </blueprint>
Next steps
Now that you have added and configured endpoints in the route, you can run the route as described in the Chapter 4, Running a Route tutorial.
Chapter 4. Running a Route
This tutorial walks you through the process of running a route to verify that the route correctly transfers messages from the source endpoint to the sink endpoint.
Goals
In this tutorial you complete the following tasks:
- Run a route as a local Camel context (without tests since you have not set up a test yet)
- Send messages through the route
- Examine the messages received by the sink endpoint to make sure that the route correctly processed the test messages
Prerequisites
To start this tutorial, you need the ZooOrderApp project resulting from:
- Completing the Chapter 2, Setting up your environment tutorial.
One of the following:
Completing the Chapter 3, Defining a Route tutorial.
or
-
Replacing your project’s
blueprint.xml
file with the providedblueprintContexts/blueprint1.xml
file, as described in the section called “About the resource files”.
Running the route
To run the route:
-
Open the
ZooOrderApp
project. In Project Explorer, select
ZooOrderApp/Camel Contexts/blueprint.xml
:Right-click the
blueprint.xml
, and then select Run As → Local Camel Context (without tests).NoteIf you select Local Camel Context instead, the tooling automatically tries to run the routing context against a supplied JUnit test. Because a JUnit test does not exist, the tooling reverts to running the routing context without tests. In the Chapter 9, Testing a route with JUnit tutorial, you create a JUnit test case to test the ZooOrderApp project.
The Console panel opens to display log messages that reflect the progress of the project’s execution. At the beginning, Maven downloads the resources necessary to update the local Maven repository. The Maven download process can take a few minutes.
Wait for messages (similar to the following) to appear at the end of the output. These messages indicate that the route executed successfully:
... [Blueprint Event Dispatcher: 1] BlueprintCamelContext INFO Route: _route1 started and consuming from:Endpoint[file://src/data?noop=true] [Blueprint Event Dispatcher: 1] BlueprintCamelContext INFO Total 1 routes, of which 1 are started. [Blueprint Event Dispatcher: 1]BlueprintCamelContext INFO Apache Camel 2.21.0.redhat-3 (CamelContext: ...) started in 0.163 seconds [Blueprint Event Dispatcher: 1] BlueprintCamelContext INFO Apache Camel 2.21.0.redhat-3 (CamelContext: ...) started in 0.918 seconds
- To shutdown the route, click located at the top of the Console view.
Verifying the route
To verify that the route executed properly, you check to see whether the message XML files were copied from the source folder (src/data
) to the target folder (target/messages/received
).
-
In Project Explorer, select
ZooOrderApp
. - Right-click and then select Refresh.
In Project Explorer, locate the
target/messages/
folder and expand it to verify that thetarget/messages/received
folder contains the six message files,message1.xml
throughmessage6.xml
:Double-click
message1.xml
to open it in the route editor’s Design tab, and then select the Source tab to see the XML code:<?xml version="1.0" encoding="UTF-8"?> <order> <customer> <name>Bronx Zoo</name> <city>Bronx NY</city> <country>USA</country> </customer> <orderline> <animal>wombat</animal> <quantity>12</quantity> </orderline> </order>
Next steps
In the Chapter 5, Adding a Content-Based Router tutorial you add a Content-Based Router that uses the content of a message to determine its destination.
Chapter 5. Adding a Content-Based Router
This tutorial shows how to add a Content-Based Router (CBR) and logging to a route.
A CBR routes a message to a destination based on its content. In this tutorial, the CBR that you create routes messages to different folders (valid or invalid) based on the value of each message’s quantity field (the number of animals in the order). The maximum value of animals for each order is 10. The CBR routes the messages to different folders, depending on whether the quantity is greater than 10. For example, if a zoo orders five zebras and only three zebras are available, the order is copied to the invalid order target folder.
Goals
In this tutorial you complete the following tasks:
- Add a Content-Based Router to your route
Configure the Content-Based Router:
- Add a log endpoint to each output branch of the content-based router
- Add a Set Header EIP after each log endpoint
- Add an Otherwise branch to the content-based router
Prerequisites
To start this tutorial, you need the ZooOrderApp project resulting from one of the following:
Completing the Chapter 4, Running a Route tutorial.
or
-
Completing the Chapter 2, Setting up your environment tutorial and replacing your project’s
blueprint.xml
file with the providedblueprintContexts/blueprint1.xml
file, as described in the section called “About the resource files”.
Adding and configuring a Content-Based Router
To add and configure a Content-Based Router for your route:
-
In Project Explorer, double-click
ZooOrderApp/src/main/resources/OSGI-INF/blueprint/blueprint.xml
to open it in the Editor view. -
On the Design canvas, select the
To_Received
node and then select the trash can icon to delete it. In the Palette, open the Routing drawer, click a Choice ( ) pattern, and then (in the Design canvas) click the
From_from1
node.The
Route_route1
container expands to accommodate theChoice_choice1
node. The error icon indicates that theChoice_choice1
node requires a child node, which you add next.From the Routing drawer, click the When ( ) pattern and then, in the canvas, click the
Choice_choice1
node.The
Choice_choice1
container expands to accommodate theWhen_when1
node:The decorating the
When_when1
node indicates that one or more required property values must be set.NoteThe tooling prevents you from adding a pattern to an invalid drop point in a Route container.
On the canvas, select the
When_when1
node, to open its properties in the Properties view:- Click the button in the Expression field to open the list of available options.
Select xpath (for the XML query language) because the test messages are written in XML.
NoteOnce you select the Expression language, the Properties view displays its properties in an indented list directly below the Expression field. The Id property in this indented list sets the ID of the expression. The Id property following the Description field sets the ID of the
When
node.In the indented Expression field, type:
/order/orderline/quantity/text() > 10
This expression specifies that only messages in which the value of the quantity field is greater than 10 travel this path in the route (to the invalidOrders folder).
Leave each of the remaining properties as they are.
NoteThe Trim option (enabled by default) removes any leading or trailing white spaces and line breaks from the message.
- Save the routing context file.
Click the Source tab to view the XML for the route:
Adding and configuring logging
For the ZooOrder application example, you add a log message so that you can track an XML message as it passes through the route. When you run the route, the log message appears in the Console view.
Follow these steps to add logging to your CBR route:
- In the Design tab’s Palette, open the Components drawer and click the Log component ( ).
In the canvas, click the
When_when1
node.The
When_when1
container expands to accommodate theLog_log1
node:-
On the canvas, select the
Log_log1
node to open its properties in the Properties view. In the Message field, type:
The quantity requested exceeds the maximum allowed - contact customer.
Leave the remaining properties as they are.
+
The tooling auto-generates a log node id value. In the Fuse Integration perspective’s Messages view, the tooling inserts the contents of the log node’s Id field in the Trace Node Id column for message instances, when tracing is enabled on the route (see the Chapter 8, Tracing a message through a route tutorial). In the Console, it adds the contents of the log node’s Message field to the log data whenever the route runs.
- Save the routing context file.
Adding and configuring message headers
A message header contains information to process a message.
To add and configure message headers:
- In the Palette, open the Transformation drawer and then click the Set Header ( ) pattern.
In the canvas, click the
Log_log1
node.The
When_when1
container expands to accommodate theSetHeader_setHeader1
node:On the canvas, select the
SetHeader_setHeader1
node to open its properties in the Properties view:- Click the button in the Expression field to open the list of available languages, and then select constant.
-
In the indented Expression field, type
Invalid
. -
In the Header Name field, type
Destination
. Leave the remaining properties as they are.
- In the Palette, open the Components drawer and then click the File ( ) component.
In the canvas, click the
SetHeader_setHeader1
node.The
When_when1
container expands to accommodate theTo_to1
node.On the canvas, select the
To_to1
node to open its properties in the Properties view:On the Details tab, replace directoryName with
target/messages/invalidOrders
in the Uri field, and type_Invalid
in the Id field:- Save the routing context file.
Click the Source tab to view the XML for the route:
Adding and configuring a branch to handle valid orders
So far, the CBR handles messages that contain invalid orders (orders where the quantity value is greater than 10).
To add and configure an otherwise branch of your route to handle valid orders (that is, any XML messages that do not match the XPath expression set for the When_when1 node):
- In the Palette, open the Routing drawer and click the Otherwise ( ) pattern.
In the canvas, click the
Choice_choice1
container:The
Choice_choice1
container expands to accommodate theOtherwise_otherwise1
node.-
On the canvas, select the
Otherwise_otherwise1
node to open its properties in the Properties view. In the Id field, change
_otherwise1
to_elseValid
:
To configure logging for the otherwise branch:
- In the Palette, open the Components drawer and and then click the Log ( ) component.
In the canvas, click the
Otherwise_elseValid
node:The
Otherwise-elseValid
container expands to accommodate theLog_log2
node.-
On the canvas, select the
Log_log2
node to open its properties in the Properties view. In the Message field, type
This is a valid order - OK to process.
Leave the remaining properties as they are.
- Save the route.
To configure a message header for the otherwise branch:
- In the Palette, open the Transformation drawer and then click the Set Header pattern.
In the canvas, click the
Log_log2
node.The
Otherwise_elseValid
container expands to accommodate theSetHeader_setHeader2
node.NoteYou can collapse containers to free up space when the diagram becomes congested. To do so, select the container you want to collapse, and then click its button:
To reopen the container, select it and then click its button:
Collapsing and expanding containers in the Design tab does not affect the routing context file. It remains unchanged.
-
On the canvas, select the
SetHeader_setHeader2
node to open its properties in the Properties view. - Click the button in the Expression field to open the list of available languages, and select constant.
-
In the indented Expression field, type
ReadyForDispatcher
. -
In the Header Name field, type
Destination
. Leave the remaining properties as they are.
To specify the target folder for the valid messages:
- In the Palette, open the Components drawer and then select the File ( ) component.
In the canvas, click the
SetHeader_setHeader2
node.The
Otherwise_elseValid
container expands to accommodate theTo_to1
node.-
On the canvas, select the
To_to1
node to open its properties in the Properties view. In the URI field, replace directoryName with
target/messages/validOrders
, and in the Id field, type_Valid
.Save the routing context file.
The completed content-based router should look like this:
Click the Source tab at the bottom, left of the canvas to display the XML for the route.
<?xml version="1.0" encoding="UTF-8"?> <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd"> <camelContext id="_context1" xmlns="http://camel.apache.org/schema/blueprint"> <route id="_route1"> <from id="_from1" uri="file:src/data?noop=true"/> <choice id="_choice1"> <when id="_when1"> <xpath>/order/orderline/quantity/text() > 10</xpath> <log id="_log1" message="The quantity requested exceeds the maximum allowed - contact customer."/> <setHeader headerName="Destination" id="_setHeader1"> <constant>Invalid</constant> </setHeader> <to id="_Invalid" uri="file:target/messages/invalidOrders"/> </when> <otherwise id="_elseValid"> <log id="_log2" message="This is a valid order - OK to process."/> <setHeader headerName="Destination" id="_setHeader2"> <constant>ReadyForDispatcher</constant> </setHeader> <to id="_Valid" uri="file:target/messages/validOrders"/> </otherwise> </choice> </route> </camelContext> </blueprint>
Verifying the CBR
You can run the new route as described in the the section called “Running the route” tutorial and look at the Console view to see the log messages.
After you run it, to verify whether the route executed properly, check the target destination folders in the Project Explorer:
-
Select
ZooOrderApp
. - Right-click it to open the context menu, and then select Refresh.
Under the project root node (
ZooOrderApp
), locate thetarget/messages/
folder and expand it.Check that the
target/messages/invalidOrders
folder containsmessage1.xml
andmessage3.xml
.In these messages, the value of the
quantity
element exceeds 10.Check that the
target/messages/validOrders
folder contains the four message files that contain valid orders:-
message2.xml
-
message4.xml
-
message5.xml
message6.xml
In these messages, the value of the
quantity
element is less than or equal to 10.NoteTo view message content, double-click each message to open it in the route editor’s XML editor.
-
Next steps
In the next tutorial, Chapter 6, Adding another route to the routing context, you add a second route that further processes valid order messages.
Chapter 6. Adding another route to the routing context
This tutorial shows you how to add a second route to the camel context in the ZooOrderApp
project’s blueprint.xml
file. The second route:
- Takes messages (valid orders) directly from the terminal end of the first route’s otherwise branch.
- Sorts the valid messages according to the customer’s country.
-
Sends each message to the corresponding
country
folder in theZooOrderApp/target/messages
folder. For example, an order from the Chicago zoo is copied to the USA folder.
Goals
In this tutorial you complete the following tasks:
- Reconfigure the existing route for direct connection to a second route
- Add a second route to your Camel context
- Configure the second route to take messages directly from the otherwise branch of the first route
- Add a content-based router to the second route
- Add and configure a message header, logging, and target destination to each output branch of the second route’s content-based router
Prerequisites
To start this tutorial, you need the ZooOrderApp project resulting from one of the following:
Complete the Chapter 5, Adding a Content-Based Router tutorial.
or
-
Complete the Chapter 2, Setting up your environment tutorial and replace your project’s
blueprint.xml
file with the providedblueprintContexts/blueprint2.xml
file, as described in the section called “About the resource files”.
Reconfiguring the existing route’s endpoint
The existing route sends all valid orders to the target/messages/validOrders
folder.
In this section, you reconfigure the endpoint of the existing route’s Otherwise _elseValid branch to instead connect to a second route (which you create in the next section).
To configure the existing route for direct connection with the second route:
-
Open your
ZooOrderApp/src/main/resources/OSGI-INF/blueprint/blueprint.xml
in the route editor. - On the canvas, select the Route_route1 container to open its properties in the Properties view.
- Scroll down to the Shutdown Route property and then select Default.
- On the canvas, select the terminal file node To_Valid to display its properties in the Properties view.
-
In the Uri field, delete the existing text, and then enter
direct:OrderFulfillment
. -
In the Id field, enter
_Fulfill
.
Instead of repurposing the existing To_Valid
terminal file node, you could have replaced it with a Components → Direct component, configuring it with the same property values as the repurposed To_Valid
node.
To learn more about the Direct component see the Apache Camel Component Reference.
Adding the second route
To add another route to the routing context:
- In the Palette, open the Routing drawer and then click the Route ( ) pattern.
In the canvas, click to the right of the
Route_route1
container:The Route pattern becomes the
Route_route2
container node on the canvas.-
Click the
Route_route2
container node to display its properties in the Properties view. Leave the properties as they are. - Save the file.
As your routing context grows in complexity, you might want to focus the route editor on an individual route while you work on it. To do so, in Project Explorer, double-click the route that you want the route editor to display on the canvas; for example Route_route2
:
To display all routes in the routing context on the canvas, double-click the project’s .xml
context file entry (src/main/resources/OSGI-INF/…
) at the top of the Camel Contexts
folder.
Configuring a Choice branch to process USA orders
In this section, you add a Choice branch to the route and configure the route to send USA orders to a new target/messages/validOrders/USA
folder. You also set a message header and a log file component.
- In the Palette, open the Components drawer and then select the Direct component ( ).
In the canvas, click the
Route_route2
container:The
Route_route2
container expands to accommodate the Direct component (theFrom_from2
node):-
On the canvas, click the
From_from2
node to open its properties in the Properties view. In the Uri field, replace
name
(followingdirect:
) withOrderFulfillment
, and in the Id field, enter_direct:OrderFulfillment
.- In the Palette, open the Routing drawer and then select the Choice ( ) pattern.
In the canvas, click the
From _direct:OrderFulfillment
node.The
Route_route2
container expands to accommodate theChoice_choice2
node:In the Properties view, leave the
Choice_choice2
node’s properties as they are.- In the Palette, open the Routing drawer and then select the When ( ) pattern.
In the canvas, click the
Choice_choice2
node.The
Choice_choice2
container expands to accommodate theWhen_when2
node.-
On the canvas, select the
When_when2
node to open its properties in the Properties view. Set the
When_when2
node’s properties as follows:- Select xpath from the Expression drop-down list.
-
In the indented Expression field, type
/order/customer/country = 'USA'
. - Leave Trim enabled.
In the second Id field, type
_when/usa
- In the Palette, open the Components drawer and then select the File component ( ).
In the canvas, click the
When_when/usa
container.The
When_when/usa
container expands to accommodate theTo_to1
node.In the Properties view:
-
In the Uri field, replace
directoryName
withtarget/messages/validOrders/USA
. -
In the Id field, type
_US
.
-
In the Uri field, replace
- Save the file.
To set a message header and add a log component:
- In the Palette, open the Transformation drawer and then select the Set Header pattern.
In the canvas, click the
When_when/usa
node.The
When_when/usa
container expands to accommodate theSetHeader_setHeader3
node:-
On the canvas, select the
SetHeader_setHeader3
node to open its properties in the Properties view. Set the node’s properties as follows:
- From the Expression drop-down menu, select constant.
-
In the indented Expression field, type:
USA
- Leave Trim enabled.
-
In the Header Name field, type:
Destination
In the second Id field, type:
_setHead_usa
- In the Palette, open the Components drawer and then select the Log component ( ).
In the canvas, click above the
SetHeader
node.The
When_when/usa
container expands to accommodate theLog_log3
node.On the canvas, select the
Log_log3
node to open its properties in the Properties view:In the Properties view:
-
In the Message field, type
Valid order - ship animals to USA customer
. -
In the Id field, type
_usa
. Leave Logging Level as is.
-
In the Message field, type
Save the file.
The USA branch of
Route_route2
should look like this:
Configuring an Otherwise branch to process Germany orders
With Route_route2
displayed on the canvas:
- In the Palette, open the Routing drawer and then select the Otherwise pattern ( ).
In the canvas, click the
Choice_choice2
container.The
Choice_choice2
container expands to accommodate theOtherwise_otherwise1
node.-
Select the
Otherwise_otherwise1
node to open its properties in the Properties view. -
In the Properties view, enter
_else/ger
for the Id field. - In the Palette, open the Transformation drawer and then select the Set Header pattern ( ).
In the canvas, click the
Otherwise_else/ger
node.The
Otherwise_else/ger
container expands to accommodate theSetHeader_setHeader3
node.-
On the canvas, select the
SetHeader_setHeader3
node to open its properties in the Properties view. In the Properties view:
- From the Expression drop-down list, select constant.
-
In the second Expression field, type
Germany
. - Leave Trim as is.
-
In the Header Name field, type
Destination
. -
In the second Id field, type
_setHead_ger
.
- In the Palette, open the Components drawer and then select the Log pattern ( ).
In the canvas, click below the
SetHeader_setHead_ger
node.The
Otherwise_else/ger
container expands to accommodate theLog_log3
node. If needed, drag the connector error from theLog_log3
node to theSetHeader_setHead_ger
node:-
On the canvas, select the
Log_log3
node to open its properties in the Properties view. In the Properties view:
-
In the Message field, type
Valid order - ship animals to Germany customer
. -
In the Id field, type
_ger
. - Leave the Logging Level as is.
-
In the Message field, type
In the Components drawer, select a File pattern ( ) and then click below the
Log_ger
node.The
Otherwise_else/ger
container expands to accommodate theTo_to1
node. If needed, drag the connector error from theSetHeader_setHead_ger
node to theTo_to1
node:-
On the canvas, select the
To_to1
node to open its properties in the Properties view. In the Properties view:
-
In the Uri field, replace
directoryName
withtarget/messages/validOrders/Germany
-
In the Id field, type
_GER
.
-
In the Uri field, replace
- Save the file.
The Germany branch of Route_route2
should look like this:
Verifying the second route
The routes on the canvas should look like this:
Completed route1
Completed route2
In the Source tab at the bottom of the canvas, the XML for the camelContext element should look like that shown in Example 6.1, “XML for dual-route content-based router”:
Example 6.1. XML for dual-route content-based router
<?xml version="1.0" encoding="UTF-8"?> <blueprint xmlns="http://www.osgi.org/xmlns/blueprint/v1.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.osgi.org/xmlns/blueprint/v1.0.0 https://www.osgi.org/xmlns/blueprint/v1.0.0/blueprint.xsd http://camel.apache.org/schema/blueprint http://camel.apache.org/schema/blueprint/camel-blueprint.xsd"> <camelContext id="_context1" xmlns="http://camel.apache.org/schema/blueprint"> <route id="_route1" shutdownRoute="Default"> <from id="_from1" uri="file:src/data?noop=true"/> <choice id="_choice1"> <when id="_when1"> <xpath>/order/orderline/quantity/text() > 10</xpath> <log id="_log1" message="The quantity requested exceeds the maximum allowed - contact customer."/> <setHeader headerName="Destination" id="_setHeader1"> <constant>Invalid</constant> </setHeader> <to id="_Invalid" uri="file:target/messages/invalidOrders"/> </when> <otherwise id="_elseValid"> <log id="_log2" message="This is a valid order - OK to process."/> <setHeader headerName="Destination" id="_setHeader2"> <constant>ReadyForDispatcher</constant> </setHeader> <to id="_Fulfill" uri="direct:OrderFulfillment"/> </otherwise> </choice> </route> <route id="_route2"> <from id="_direct:OrderFulfillment" uri="direct:OrderFulfillment"/> <choice id="_choice2"> <when id="when/usa"> <xpath>/order/customer/country = 'USA'</xpath> <log id="_usa" message="Valid order - ship animals to USA customer"/> <setHeader headerName="Destination" id="_setHead_usa"> <constant>USA</constant> </setHeader> <to id="_US" uri="file:target/messages/validOrders/USA"/> </when> <otherwise id="_else/ger"> <log id="_ger" message="Valid order - ship animals to Germany customer"/> <setHeader headerName="Destination" id="_setHead_ger"> <constant>Germany</constant> </setHeader> <to id="_GER" uri="file:target/messages/validOrders/Germany"/> </otherwise> </choice> </route> </camelContext> </blueprint>
If the tooling added the attribute shutdownRoute=" "
to the second route element (<route id="route2">
), delete that attribute. Otherwise, the ZooOrderApp
project might fail to run.
To make sure that your updated project works as expected, follow these steps:
-
Run the
ZooOrderApp/Camel Contexts/blueprint.xml
as a local Camel Context (without tests). Check the end of the Console’s output. You should see these lines:
Check the target destination folders to verify that the routes executed properly:
-
In Project Explorer, right-click
ZooOrderApp
and then select Refresh. Expand the
target/messages/
folder.The
message*.xml
files should be dispersed in your the destinations as shown:Figure 6.1. Target message destinations in Project Explorer
-
In Project Explorer, right-click
Next steps
In the next tutorial, Chapter 7, Debugging a routing context, you learn how to use the Fuse Tooling debugger.
Chapter 7. Debugging a routing context
This tutorial shows how to use the Camel debugger to find logic errors for a locally running routing context.
Goals
In this tutorial you complete the following tasks:
- Set breakpoints on the nodes of interest in the two routes
- In the Debug perspective, step through the routes and examine the values of message variables
- Step through the routes again, changing the value of a message variable and observing the effect
Prerequisites
To start this tutorial, you need the ZooOrderApp project resulting from one of the following:
Complete the Chapter 6, Adding another route to the routing context tutorial.
or
-
Complete the Chapter 2, Setting up your environment tutorial and replace your project’s
blueprint.xml
file with the providedblueprintContexts/blueprint3.xml
file, as described in the section called “About the resource files”.
Setting breakpoints
In the Debugger, you can set both conditional and unconditional breakpoints. In this tutorial, you only set unconditional breakpoints. To learn how to set conditional breakpoints (that are triggered when a specific condition is met during the debugging session), see the Tooling User Guide.
To set unconditional breakpoints:
-
If necessary, open your
ZooOrderApp/src/main/resources/OSGI-INF/blueprint/blueprint.xml
in the route editor. -
In Project Explorer, expand
Camel Contexts
→src/main/resources/OSGI-INF/blueprint/blueprint.xml
to expose both route entries. -
Double-click the Route_route1 entry to switch focus to
Route_route1
in the Design tab. On the canvas, select the
Choice_choice1
node, and then click its icon to set an unconditional breakpoint:NoteIn the route editor, you can disable or delete a specific breakpoint by clicking the node’s icon or its icon, respectively. You can delete all set breakpoints by right-clicking the canvas and selecting Delete all breakpoints.
Set unconditional breakpoints on the following
Route_Route1
nodes:-
Log_log1
-
SetHeader_setHeader1
-
To_Invalid
-
Log_log2
-
SetHeader_setHeader2
-
To_Fulfill
-
-
In Project Explorer, double-click
Route_route2
undersrc/main/resources/OSGI-INF/blueprint
to openRoute_route2
on the canvas. Set unconditional breakpoints on the following
Route_Route2
nodes:-
Choice_choice2
-
SetHeader_setHead_usa
-
Log_usa
-
To_US
-
SetHeader_setHead_ger
-
Log_ger
-
To_GER
-
Stepping through the routing context
You can step through the routing context in two ways:
- Step over ( ) - Jumps to the next node of execution in the routing context, regardless of breakpoints.
Resume ( ) - Jumps to the next active breakpoint in the routing context.
-
In Project Explorer, expand the
ZooOrderApp
project’sCamel Contexts
folder to expose theblueprint.xml
file. Right-click the
blueprint.xml
file to open its context menu, and then click Debug As → Local Camel Context (without tests).The Camel debugger suspends execution at the first breakpoint it encounters and asks whether you want to open the Debug perspective now:
Click Yes.
NoteIf you click No, the confirmation pane appears several more times. After the third refusal, it disappears, and the Camel debugger resumes execution. To interact with the debugger at this point, you need to open the Debug perspective by clicking Window → Open Perspective → > Debug.
The Debug perspective opens with the routing context suspended at
_choice1 in _route1 [blueprint.xml]
as shown in the Debug view:NoteBreakpoints are held for a maximum of five minutes before the debugger automatically resumes, moving on to the next breakpoint or to the end of the routing context, whichever comes next.
In the Variables view, expand the nodes to expose the variables and values available for each node.
As you step through the routing context, the variables whose values have changed since the last breakpoint are highlighted in yellow. You might need to expand the nodes at each breakpoint to reveal variables that have changed.
Click to step to the next breakpoint,
_log2 in _route1 [blueprint.xml]
:-
Expand the nodes in the Variables view to examine the variables that have changed since the last breakpoint at
_choice1 in Route1 [blueprintxt.xml]
. Click to step to the next breakpoint,
_setHeader2 in Route1 [blueprint.xml]
.Examine the variables that changed (highlighted in yellow) since the breakpoint at
_log2 in Route1 [blueprint.xml]
.In the Debug view, click
_log2 in _route1 [blueprint.xml]
to populate the Variables view with the variable values from the breakpoint_log2 in _route1 [blueprint.xml]
for a quick comparison.In the Debug view, you can switch between breakpoints within the same message flow to quickly compare and monitor changing variable values in the Variables view.
NoteMessage flows can vary in length. For messages that transit the
InvalidOrders
branch ofRoute_route1
, the message flow is short. For messages that transit theValidOrders
branch ofRoute_route1
, which continues on toRoute_route2
, the message flow is longer.Continue stepping through the routing context. When one message completes the routing context and the next message enters it, the new message flow appears in the Debug view, tagged with a new breadcrumb ID:
In this case,
ID-janemurpheysmbp-home-55846-1471374645179-0-3
identifies the second message flow, corresponding tomessage2.xml
having entered the routing context. Breadcrumb IDs are incremented by 2.NoteExchange and Message IDs are identical and remain unchanged throughout a message’s passage through the routing context. Their IDs are constructed from the message flow’s breadcrumb ID, and incremented by 1. So, in the case of
message2.xml
, itsExchangeId
andMessageId
areID-janemurpheysmbp-home-55846-1471374645179-0-4
.When
message3.xml
enters the breakpoint_choice1 in _route_route1 [blueprint.xml]
, examine the Processor variables. The values displayed are the metrics accumulated formessage1.xml
andmessage2.xml
, which previously transited the routing context:Timing metrics are in milliseconds.
-
Continue stepping each message through the routing context, examining variables and console output at each processing step. When
message6.xml
enters the breakpointTo_GER in Route2 [blueprint.xml]
, the debugger begins shutting down the breadcrumb threads. In the Menu bar, click to terminate the Camel debugger. The Console terminates, but you must manually clear the output.
NoteWith a thread or endpoint selected under the Camel Context node in the Debug view, you must click twice - first to terminate the thread or endpoint and second to terminate the Camel Context, thus the session.
In the Menu bar, right-click to open the context menu, and then select Close to close Debug perspective.
CodeReady Studio automatically returns to the perspective from which you launched the Camel debugger.
In Project Explorer, right-click the project and then select Refresh to refresh the display.
NoteIf you terminated the session prematurely, before all messages transited the routing context, you might see, under the
ZooOrderApp/src/data
folder, a message like this:message3.xml.camelLock
. You need to remove it before you run the debugger on the project again. To do so, double-click the.camelLock
message to open its context menu, and then select Delete. When asked, click OK to confirm deletion.Expand the
ZooOrderApp/target/messages/
directories to check that the messages were delivered to their expected destinations:
-
In Project Explorer, expand the
Leave the routing context as is, with all breakpoints set and enabled.
Changing the value of a variable
In this section, you add variables to a watch list to easily check how their values change as messages pass through the routing context. You change the value of a variable in the body of a message and then observe how the change affects the message’s route through the routing context.
-
To rerun the Camel debugger on the
ZooOrderApp
project, right-click theblueprint.xml
file and then click Debug As → Local Camel Context (without tests). With
message1
stopped at the first breakpoint,_choice1 in _route1 [blueprint.xml]
, add the variablesNodeId
andRouteId
(in theExchange
category) andMessageBody
andCamelFileName
(in theMessage
category) to the watch list.For each of the four variables:
- In the Variables view, expand the appropriate category to expose the target variable:
Right-click the variable (in this case,
NodeId
in theExchange
category) to open the context menu and select Watch:The Expressions tab opens, listing the variable you selected to watch:
NoteCreating a watch list makes it easy for you to quickly check the current value of multiple variables of interest.
-
Step
message1
through the routing context until it reaches the fourth breakpoint,_Fulfill in _route1 [blueprint.xml]
. -
In the Variables view, expand the
Message
category. Add the variable
Destination
to the watch list.The Expressions view should now contain these variables:
Note- The pane below the list of variables displays the value of the selected variable.
- The Expressions view retains all variables that you add to the list until you explicitly remove them.
-
Step
message1
through the rest of the routing context and then stepmessage2
all of the way through. -
Stop
message3
at_choice1 in _route1 [blueprint.xml]
. -
In the Variables view, expand the
Message
category to expose theMessageBody
variable. Right-click
MessageBody
to open its context menu, and select Change Value:Change the value of
quantity
from 15 to 10 (to change it from an invalid order to a valid order):This changes the in-memory value only (it does not edit the
message3.xml
file).- Click OK.
Switch to the Expressions view, and select the
MessageBody
variable.The pane below the list of variables displays the entire body of
message3
, making it easy to check the current value of order items:Click to step to the next breakpoint.
Instead of following the branch leading to
To_Invalid
,message3
now follows the branch leading toTo_Fulfill
andRoute_route2
.
Narrowing the Camel debugger’s focus
You can temporarily narrow and then re-expand the debugger’s focus by disabling and re-enabling breakpoints:
-
Step
message4
through the routing context, checking the Debug view, the Variables view, and the Console output at each step. -
Stop
message4
at_choice1 in _route1 [blueprint.xml]
. Switch to the Breakpoints view, and clear each check box next to the breakpoints listed below
_choice1
. Clearing the check box of a breakpoint temporarily disables it.Click to step to the next breakpoint:
The debugger skips over the disabled breakpoints and jumps to
_FulFill in _route1 [blueprint.xml]
.Click again to step to the next breakpoint:
The debugger jumps to
_GER in _route2 [blueprint.xml]
.-
Click
repeatedly to quickly step
message5
andmessage6
through the routing context. - Switch to the Breakpoints view, and check the boxes next to all breakpoints to reenable them.
Verifying the effect of changing a message variable value
To stop the debugger and check the results of changing the value of `message1’s quantity variable:
In the tool bar, click to terminate the Camel debugger:
- Click the Console’s button to clear the output.
- Close the Debug perspective and return to the perspective from which you launched the Camel debugger.
- In Project Explorer, refresh the display.
Expand the
ZooOrderApp/target/messages/
directories to check whether the messages were delivered as expected:You should see that only
message1
was sent to theinvalidOrders
and thatmessage3.xml
appears in thevalidOrders/Germany
folder.
Next steps
In the Chapter 8, Tracing a message through a route tutorial, you trace messages through your routing context to determine where you can optimize and fine tune your routing context’s performance.
Chapter 8. Tracing a message through a route
Tracing allows you to intercept a message as it is routed from one node to another. You can trace messages through your routing context to see where you can optimize and fine tune your routing context’s performance. This tutorial shows you how to trace a message through a route.
Goals
In this tutorial you complete the following tasks:
-
Run the
ZooOrderApp
in the Fuse Integration perspective -
Enable tracing on the
ZooOrderApp
-
Drop messages onto the
ZooOrderApp
and track them through all route nodes
Prerequisites
To start this tutorial, you need the ZooOrderApp project resulting from one of the following:
Complete the Chapter 6, Adding another route to the routing context tutorial.
or
-
Complete the Chapter 2, Setting up your environment tutorial and replace your project’s
blueprint.xml
file with the providedblueprintContexts/blueprint3.xml
file, as described in the section called “About the resource files”.
Setting up your Fuse Integration perspective
To set up your workspace to facilitate message tracing:
Click the button on the right side of the tool bar, and then select Fuse Integration from the list:
The Fuse Integration perspective opens in the default layout:
Drag the JMX Navigator tab to the far right of the Terminal tab and drop it there:
This arrangement provides more space for Diagram View to display the routing context’s nodes graphically, which makes it easier for you to visually trace the path that messages take in traversing the routing context.
NoteTo make it easy to access a routing context
.xml
file, especially when a project consists of multiple contexts, the tooling lists them under theCamel Contexts
folder in Project Explorer.Additionally, all routes in a routing context are displayed as icons directly under their context file entry. To display a single route in the routing context on the canvas, double-click its icon in Project Explorer. To display all routes in the routing context, double-click the context file entry.
Starting message tracing
To start message tracing on the ZooOrderApp
project:
-
In Project Explorer, expand the
ZooOrderApp
project to exposesrc/main/resources/OSGI-INF/blueprint/blueprint.xml
. -
Right-click
src/main/resources/OSGI-INF/blueprint/blueprint.xml
to open the context menu. Select Run As → Local Camel Context (without tests).
NoteIf you select Local Camel Context, the tooling reverts to running without tests because you have not yet created a JUnit test for the
ZooOrderApp
project. You will do that later in Chapter 9, Testing a route with JUnit.In JMX Navigator, expand
Local Processes
.-
Right-click the
maven [ID]
node and then select Connect. Expand the elements of your route:
Right-click the
Routes
node and then select Start Tracing:The tooling displays a graphical representation of your routing context in Diagram View:
To see all message flow paths clearly, you probably need to rearrange the nodes by dragging them to fit neatly in the Diagram View tab. You may also need to adjust the size of the other views and tabs in Red Hat CodeReady Studio to allow the Diagram View tab to expand.
Dropping messages on the running ZooOrderApp project
To drop messages on the running ZooOrderApp project:
In Project Explorer, expand
ZooOrderApp/src/data
, so that you can access the message files (message1.xml
throughmessage6.xml
):Drag
message1.xml
and drop it on the_context1>Endpoints>file>src/data?noop=true
node in JMX Navigator:As the message traverses the route, the tooling traces and records its passage at each step.
Configuring Messages View
You must refresh the Messages View before it will display message traces. You also need to configure the columns in Messages View if you want them to persist across all message traces.
- Open the Messages View.
-
Click the
(Refresh button) on top, right of the panel’s menu bar to populate the view with
message1.xml
's message traces. Click the icon on the panel’s menu bar, and select Configure Columns to open the Configure Columns wizard:
NoteNotice that the message header, Destination, which you set for the messages in your routing context, appears in the list.
You can include or exclude items from Messages View by selecting or deselecting them. You can rearrange the columnar order in which items appear in Messages View by highlighting individual, selected items and moving them up or down in the list.
In the Configure Columns wizard, select and order the columns this way:
These columns and their order will persist in Messages View until you change them again.
You can control columnar layout in all of the tooling’s tables. Use the drag method to temporarily rearrange tabular format. For example, drag a column’s border rule to expand or contract its width. To hide a column, totally contract its borders. Drag the column header to relocate a column within the table. For your arrangement to persist, you must use the View → Configure Columns method instead.
Stepping through message traces
To step through the message traces:
-
Drag
message2.xml
and drop it on the_context1>Endpoints>file>src/data?noop=true
node in JMX Navigator. - Switch from Console to Messages View.
In Messages View, click the (Refresh button) to populate the view with
message2.xml
message traces.Each time you drop a message on in JMX Navigator, you need to refresh Messages View to populate it with the message traces.
Click one of the message traces to see more details about it in Properties view:
The tooling displays the details about a message trace (including message headers when they are set) in the top half of the Properties view and the contents of the message instance in the bottom half of the Properties view. So, if your application sets headers at any step within a route, you can check the Message Details to see whether they were set as expected.
You can step through the message instances by highlighting each one to see how a particular message traversed the route and whether it was processed as expected at each step in the route.
Open Diagram View, to see that the associated step in the route is highlighted:
The tooling draws the route in Diagram View, tagging paths exiting a processing step with timing and performance metrics (in milliseconds). Only the metric Total exchanges is displayed in the diagram.
Hover the mouse pointer over the displayed metrics to reveal additional metrics about message flow:
- Mean time the step took to process a message
- Maximum time the step took to process a message
- Minimum time the step took to process a message
Optionally, you can drag and drop the remaining messages in
ZooOrderApp/src/data/
into the_context1>Endpoints>file>src/data?noop=true
node in JMX Navigator at any time, as long as tracing remains enabled.On each subsequent drop, remember to click the (Refresh button) to populate Messages View with the new message traces.
When done:
-
In JMX Navigator, right-click
_context1
and select Stop Tracing Context. - Open the Console and click the button in the upper right of the panel to stop the Console. Then click the button to clear console output.
-
In JMX Navigator, right-click
Next steps
In the Chapter 9, Testing a route with JUnit tutorial, you create a JUnit test case for your project and run your project as a Local Camel Context
.
Chapter 9. Testing a route with JUnit
This tutorial shows you how to use the New Camel Test Case wizard to create a test case for your route and then test the route.
Overview
The New Camel Test Case wizard generates a boilerplate JUnit test case. When you create or modify a route (for example, adding more processors to it), you should create or modify the generated test case to add expectations and assertions specific to the route that you created or updated. This ensures that the test is valid for the route.
Goals
In this tutorial you complete the following tasks:
-
Create the
/src/test/
folder to store the JUnit test case -
Generate the JUnit test case for the
ZooOrderApp
project - Modify the newly generated JUnit test case
-
Modify the
ZooOrderApp
project’spom.xml
file -
Run the
ZooOrderApp
with the new JUnit test case - Observe the output
Prerequisites
To start this tutorial, you need the ZooOrderApp project resulting from one of the following:
Complete the Chapter 8, Tracing a message through a route tutorial.
or
-
Complete the Chapter 2, Setting up your environment tutorial and replace your project’s
blueprint.xml
file with the providedblueprintContexts/blueprint3.xml
file, as described in the section called “About the resource files”.
Delete any trace-generated messages from the
ZooOrderApp
project’s/src/data/
directory and/target/messages/
subdirectories in Project Explorer. Trace-generated messages begin with theID-
prefix. For example, Figure 9.1, “Trace-generated messages” shows eight trace-generated messages:Figure 9.1. Trace-generated messages
Select all trace-generated messages in batch, right-click and then select Delete.
Creating the src/test
folder
Before you create a JUnit test case for the ZooOrderApp
project, you must create a folder for it that is included in the build path:
-
In Project Explorer, right-click the
ZooOrderApp
project and then select New → Folder. In the New Folder dialog, in the project tree pane, expand the
ZooOrderApp
node and select thesrc
folder.Make sure
ZooOrderApp/src
appears in the Enter or select the parent folder field.In Folder name, enter
/test/java
:Click Finish.
In Project Explorer, the new
src/test/java
folder appears under thesrc/main/resources
folder:Verify that the new
/src/test/java
folder is included in the build path.-
In Project Explorer, right-click the
/src/test/java
folder to open the context menu. Select Build Path to see the menu options:
The menu option Remove from Build Path verifies that the
/src/test/java
folder is currently included in the build path:
-
In Project Explorer, right-click the
Creating the JUnit test case
To create a JUnit test case for the ZooOrderApp
project:
-
In Project Explorer, select
src/test/java
. Right-click and then select New → Camel Test Case.
-
In the Camel JUnit Test Case wizard, make sure the
Source folder
field containsZooOrderApp/src/test/java
. To find the proper folder, click . -
In the Package field, enter
tutorial.zooapp.route
. This package will include the new test case. In the Camel XML file under test field, click to open a file explorer configured to filter for XML files, and then select the
ZooOrderApp
project’sblueprint.xml
file:Click OK. The Name field defaults to BlueprintXmlTest.
Click Next to open the Test Endpoints page.
By default, all endpoints are selected and will be included in the test case.
Click Finish.
NoteIf prompted, add JUnit to the build path.
The artifacts for the test are added to your project and appear in Project Explorer under src/test/java
. The class implementing the test case opens in the tooling’s Java editor:
package tutorial.zooapp.route; import org.apache.camel.EndpointInject; import org.apache.camel.Produce; import org.apache.camel.ProducerTemplate; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; import org.apache.camel.test.blueprint.CamelBlueprintTestSupport; import org.junit.Test; public class BlueprintXmlTest extends CamelBlueprintTestSupport { // TODO Create test message bodies that work for the route(s) being tested // Expected message bodies protected Object[] expectedBodies = { "<something id='1'>expectedBody1</something>", "<something id='2'>expectedBody2</something>" }; // Templates to send to input endpoints @Produce(uri = "file:src/data?noop=true") protected ProducerTemplate inputEndpoint; @Produce(uri = "direct:OrderFulfillment") protected ProducerTemplate input2Endpoint; // Mock endpoints used to consume messages from the output endpoints and then perform assertions @EndpointInject(uri = "mock:output") protected MockEndpoint outputEndpoint; @EndpointInject(uri = "mock:output2") protected MockEndpoint output2Endpoint; @EndpointInject(uri = "mock:output3") protected MockEndpoint output3Endpoint; @EndpointInject(uri = "mock:output4") protected MockEndpoint output4Endpoint; @Test public void testCamelRoute() throws Exception { // Create routes from the output endpoints to our mock endpoints so we can assert expectations context.addRoutes(new RouteBuilder() { @Override public void configure() throws Exception { from("file:target/messages/invalidOrders").to(outputEndpoint); from("file:target/messages/validOrders/USA").to(output3Endpoint); from("file:target/messages/validOrders/Germany").to(output4Endpoint); } }); // Define some expectations // TODO Ensure expectations make sense for the route(s) we're testing outputEndpoint.expectedBodiesReceivedInAnyOrder(expectedBodies); // Send some messages to input endpoints for (Object expectedBody : expectedBodies) { inputEndpoint.sendBody(expectedBody); } // Validate our expectations assertMockEndpointsSatisfied(); } @Override protected String getBlueprintDescriptor() { return "OSGI-INF/blueprint/blueprint.xml"; } }
This generated JUnit test case is insufficient for the ZooOrderApp
project, and it will fail to run successfully. You need to modify it and the project’s pom.xml
, as described in the section called “Modifying the BlueprintXmlTest file” and the section called “Modifying the pom.xml file”.
Modifying the BlueprintXmlTest file
You must modify the BlueprintXmlTest.java
file to:
- Import several classes that support required file functions
-
Create variables for holding the content of the various source
.xml
files -
Read the content of the source
.xml
files - Define appropriate expectations
Follow these steps to modify the BlueprintXmlTest.java
file:
In Project Explorer, expand the
ZooOrderApp
project to expose theBlueprintXmlTest.java
file:-
Open the
BlueprintXmlTest.java
file. -
In the Java editor, click the expand button next to
import org.apache.camel.EndpointInject;
to expand the list. Add the two lines shown in bold text. Adding the first line causes an error that will be resolved when you update the
pom.xml
file as instructed in the next section.package tutorial.zooapp.route; import org.apache.camel.EndpointInject; import org.apache.camel.Produce; import org.apache.camel.ProducerTemplate; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; import org.apache.camel.test.blueprint.CamelBlueprintTestSupport; import org.apache.commons.io.FileUtils; import org.junit.Test; import java.io.File;
-
Scroll down to the lines that follow directly after
// Expected message bodies
. Replace those lines —
protected Object[] expectedBodies={ …… expectedBody2</something>"};
— with theseprotected String body#;
lines:protected String body1; protected String body2; protected String body3; protected String body4; protected String body5; protected String body6;
Scroll down to the line
public void testCamelRoute() throws Exception {
, and insert directly after it the linesbody# = FileUtils.readFileToString(new File("src/data/message#.xml"), "UTF-8");
shown below. These lines will indicate an error until you update thepom.xml
file as instructed in the next section.// Valid orders body2 = FileUtils.readFileToString(new File("src/data/message2.xml"), "UTF-8"); body4 = FileUtils.readFileToString(new File("src/data/message4.xml"), "UTF-8"); body5 = FileUtils.readFileToString(new File("src/data/message5.xml"), "UTF-8"); body6 = FileUtils.readFileToString(new File("src/data/message6.xml"), "UTF-8"); // Invalid orders body1 = FileUtils.readFileToString(new File("src/data/message1.xml"), "UTF-8"); body3 = FileUtils.readFileToString(new File("src/data/message3.xml"), "UTF-8");
-
Scroll down to the lines that follow directly after
// TODO Ensure expectations make sense for the route(s) we’re testing
. Replace the block of code that begins with
outputEndpoint.expectedBodiesReceivedInAnyOrder(expectedBodies);
and ends with …inputEndpoint.sendBody(expectedBody); }
with the lines shown here:// Invalid orders outputEndpoint.expectedBodiesReceived(body1, body3); // Valid orders for USA output3Endpoint.expectedBodiesReceived(body2, body5, body6); // Valid order for Germany output4Endpoint.expectedBodiesReceived(body4);
Leave the remaining code as is.
- Save the file.
Check that your updated
BlueprintXmlTest.java
file has the required modifications. It should look something like this:package tutorial.zooapp.route; import org.apache.camel.EndpointInject; import org.apache.camel.Produce; import org.apache.camel.ProducerTemplate; import org.apache.camel.builder.RouteBuilder; import org.apache.camel.component.mock.MockEndpoint; import org.apache.camel.test.blueprint.CamelBlueprintTestSupport; import org.apache.commons.io.FileUtils; import org.junit.Test; import java.io.file; public class BlueprintXmlTest extends CamelBlueprintTestSupport { // TODO Create test message bodies that work for the route(s) being tested // Expected message bodies protected String body1; protected String body2; protected String body3; protected String body4; protected String body5; protected String body6; // Templates to send to input endpoints @Produce(uri = "file:src/data?noop=true") protected ProducerTemplate inputEndpoint; @Produce(uri = "direct:OrderFulfillment") protected ProducerTemplate input2Endpoint; // Mock endpoints used to consume messages from the output endpoints and then perform assertions @EndpointInject(uri = "mock:output") protected MockEndpoint outputEndpoint; @EndpointInject(uri = "mock:output2") protected MockEndpoint output2Endpoint; @EndpointInject(uri = "mock:output3") protected MockEndpoint output3Endpoint; @EndpointInject(uri = "mock:output4") protected MockEndpoint output4Endpoint; @Test public void testCamelRoute() throws Exception { // Create routes from the output endpoints to our mock endpoints so we can assert expectations context.addRoutes(new RouteBuilder() { @Override public void configure() throws Exception { // Valid orders body2 = FileUtils.readFileToString(new File("src/data/message2.xml"), "UTF-8"); body4 = FileUtils.readFileToString(new File("src/data/message4.xml"), "UTF-8"); body5 = FileUtils.readFileToString(new File("src/data/message5.xml"), "UTF-8"); body6 = FileUtils.readFileToString(new File("src/data/message6.xml"), "UTF-8"); // Invalid orders body1 = FileUtils.readFileToString(new File("src/data/message1.xml"), "UTF-8"); body3 = FileUtils.readFileToString(new File("src/data/message3.xml"), "UTF-8"); from("file:target/messages/invalidOrders").to(outputEndpoint); from("file:target/messages/validOrders/USA").to(output3Endpoint); from("file:target/messages/validOrders/Germany").to(output4Endpoint); from("direct:OrderFulfillment").to(output2Endpoint); } }); // Define some expectations // TODO Ensure expectations make sense for the route(s) we're testing // Invalid orders outputEndpoint.expectedBodiesReceived(body1, body3); // Valid orders for USA output3Endpoint.expectedBodiesReceived(body2, body5, body6); // Valid order for Germany output4Endpoint.expectedBodiesReceived(body4); // Validate our expectations assertMockEndpointsSatisfied(); } @Override protected String getBlueprintDescriptor() { return "OSGI-INF/blueprint/blueprint.xml"; } }
Modifying the pom.xml file
You need to add a dependency on the commons-io
project to the ZooOrderApp project’s pom.xml
file:
-
In Project Explorer, select the
pom.xml
, located below thetarget
folder, and open it in the tooling’s XML editor. -
Click the
pom.xml
tab at the bottom of the page to open the file for editing. Add these lines to the end of the
<dependencies>
section:<dependency> <groupId>commons-io</groupId> <artifactId>commons-io</artifactId> <version>2.5</version> <scope>test</scope> </dependency>
- Save the file.
Running the JUnit test
To run the test:
- Switch to the JBoss perspective to free up more workspace.
-
In the Project Explorer, right-click the
ZooOrderApp
project. Select Run As → JUnit Test.
By default, the JUnit view opens in the sidebar. (To provide a better view, drag it to the bottom, right panel that displays the Console, Servers, and Properties tabs.)
NoteSometimes the test fails the first time JUnit is run on a project. Rerunning the test ususally results in a successful outcome.
If the test runs successfully, you’ll see something like this:
Figure 9.2. Successful JUnit run
When the test does fail, you’ll see something like this:
Figure 9.3. Failed JUnit run
NoteJUnit will fail if your execution environment is not set to Java SE 8. The message bar at the top of the JUnit tab will display an error message indicating that it cannot find the correct SDK.
To resolve the issue, open the project’s context menu, and select Run As → Run Configurations → JRE. Click the Environments] button next to the *Execution environment field to locate and select a Java SE 8 environment.
Examine the output and take action to resolve any test failures.
To see more of the errors displayed in the JUnit panel, click on the panel’s menu bar to maximize the view.
Before you run the JUnit test case again, delete any JUnit-generated test messages from the ZooOrderApp project’s
/src/data
folder in Project Explorer (see Figure 9.1, “Trace-generated messages”).
Further reading
To learn more about JUnit testing see JUnit.
Next steps
In the Chapter 10, Publishing your project to Red Hat Fuse tutorial, you learn how to publish your Apache Camel project to Red Hat Fuse.
Chapter 10. Publishing your project to Red Hat Fuse
This tutorial walks you through the process of publishing your project to Red Hat Fuse. It assumes that you have an instance of Red Hat Fuse installed on the same machine on which you are running the Red Hat Fuse Tooling.
Goals
In this tutorial you complete the following tasks:
- Define a Red Hat Fuse server
- Configure the publishing options
-
Start up the Red Hat Fuse server and publish the
ZooOrderApp
project - Connect to the Red Hat Fuse server
-
Verify whether the
ZooOrderApp
project’s bundle was successfully built and published -
Uninstall the
ZooOrderApp
project
Prerequisites
Before you start this tutorial you need:
- Access to a Red Hat Fuse instance
- Java 8 installed on your computer
The ZooOrderApp project resulting from one of the following:
Complete the Chapter 9, Testing a route with JUnit tutorial.
or
-
Complete the Chapter 2, Setting up your environment tutorial and replace your project’s
blueprint.xml
file with the providedblueprintContexts/blueprint3.xml
file, as described in the section called “About the resource files”.
Defining a Red Hat Fuse Server
To define a server:
- Open the Fuse Integration perspective.
- Click the Servers tab in the lower, right panel to open the Servers view.
Click the No servers are available. Click this link to create a new server… link to open the Define a New Server page.
NoteTo define a new server when one is already defined, right-click inside the Servers view and then select New → Server.
Expand the Red Hat JBoss Middleware node to expose the available server options:
- Select a Red Hat Fuse server.
Accept the defaults for Server’s host name (localhost) and Server name (Fuse n.n Runtime Server), and then click Next to open the Runtime page:
NoteIf you do not have Fuse already installed, you can download it now using the Download and install runtime link.
If you have already defined a server, the tooling skips this page, and instead displays the configuration details page.
- Accept the default for Name.
- Click Browse next to the Home Directory field, to navigate to the installation and select it.
Select the runtime JRE from the drop-down menu next to Execution Environment.
Select JavaSE-1.8 (recommended). If necessary, click the Environments button to select it from the list.
NoteThe Fuse server requires Java 8 (recommended). To select it for the Execution Environment, you must have previously installed it.
- Leave the Alternate JRE option as is.
Click Next to save the runtime definition for the Fuse Server and open the Fuse server configuration details page:
Accept the default for SSH Port (8101).
The runtime uses the SSH port to connect to the server’s Karaf shell. If this default is incorrect, you can discover the correct port number by looking in the Red Hat Fuse
installDir/etc/org.apache.karaf.shell.cfg
file.In User Name, enter the name used to log into the server.
This is a user name stored in the Red Hat Fuse installDir`/etc/users.properties` file.
NoteIf the default user has been activated (uncommented) in the
/etc/users.properties
file, the tooling autofills User Name and Password with the default user’s name and password.If one has not been set, you can either add one to that file using the format
user=password,role
(for example,joe=secret,Administrator
), or you can set one using the karafjaas
command set:-
jaas:realms
— to list the realms -
jaas:manage --index 1
— to edit the first (server) realm -
jaas:useradd <username> <password>
— to add a user and associated password -
jaas:roleadd <username> Administrator
— to specify the new user’s role jaas:update
— to update the realm with the new user informationIf a jaas realm has already been selected for the server, you can discover the user name by issuing the command
JBossFuse:karaf@root>
jaas:users
.
-
In Password, type the password required for User name to log into the server.
This is the password set either in Red Hat Fuse’s
installDir/etc/users.properties
file or by the karafjaas
commands.Click Finish.
Runtime Server [stopped, Synchronized] appears in the Servers view.
In the Servers view, expand the Runtime Server:
JMX[Disconnected] appears as a node under the Runtime Server [stopped, Synchronized] entry.
Configuring the publishing options
Using publishing options, you can configure how and when your ZooOrderApp
project is published to a running server:
- Automatically, immediately upon saving changes made to the project
- Automatically, at configured intervals after you have changed and saved the project
- Manually, when you select a publish operation
In this tutorial, you configure immediate publishing upon saving changes to the ZooOrderApp
project. To do so:
- In the Servers view, double-click the Runtime Server [stopped, Synchronized] entry to display its overview.
On the server’s Overview page, expand the Publishing section to expose the options.
Make sure that the option Automatically publish when resources change is enabled.
Optionally, change the value of Publishing interval to speed up or delay publishing the project when changes have been made.
- In the Servers view, click .
Wait a few seconds for the server to start. When it does:
The Terminal view displays the splash screen:
The Servers view displays:
The JMX Navigator displays n.n Runtime Server[Disconnected:
In the Servers view, right-click n.n Runtime Server [Started] and then select Add and Remove to open the Add and Remove page:
Make sure the option If server is started, publish changes immediately is checked.
Select
ZooOrderApp
and click Add to assign it to the Fuse server:Click Finish.
The Servers view should show the following:
Runtime Server [Started, Synchronized]
NoteFor a server, synchronized means that all modules published on the server are identical to their local counterparts.
ZooOrderApp [Started, Synchronized]
NoteFor a module, synchronized means that the published module is identical to its local counterpart. Because automatic publishing is enabled, changes made to the ZooOrderApp project are published in seconds (according to the value of the Publishing interval).
- JMX[Disconnected]
Connecting to the runtime server
After you connect to the runtime server, you can see the published elements of your ZooOrderApp
project and interact with them.
- In the Servers view, double-click JMX[Disconnected] to connect to the runtime server.
In the JMX Navigator, expand the
Camel
folder to expose the elements of theZooOrderApp
.Click the Bundles node to populate the Properties view with the list of bundles installed on the runtime server:
In the Search field, type ZooOrderApp. The corresponding bundle is shown:
NoteAlternatively, you can issue the
osgi:list
command in the Terminal view to see a generated list of bundles installed on the server runtime. The tooling uses a different naming scheme for OSGi bundles displayed by theosgi:list
command. In this case, the command returnsCamel Blueprint Quickstart
, which appears at the end of the list of installed bundles.In the
<build>
section of project’spom.xml
file, you can find the bundle’s symbolic name and its bundle name (OSGi) listed in themaven-bundle-plugin
entry:
Uninstalling the ZooOrderApp project
You do not need to disconnect the JMX connection or stop the server to uninstall a published resource.
To remove the ZooOrderApp
resource from the runtime server:
- In the Servers view, right-click n.n Runtime Server to open the context menu.
Select Add and Remove:
-
In the Configured column, select
ZooOrderApp
, and then click Remove to move theZooOrderApp
resource to the Available column. - Click Finish.
In the Servers view, right-click JMX[Connected] and then click Refresh.
The
Camel
tree under JMX[Connected] disappears.NoteIn JMX Navigator, the
Camel
tree under Server Connections > n.n Runtime Server[Connected] also disappears.- With the Bundles page displayed in the Properties view, scroll down to the end of the list to verify that the ZooOrderApp’s bundle is no longer listed.