Mule 4 + MuleSoft + Choice Router Control + Java Module + Example

  • In this article we will learn Choice Router in MuleSoft Message Flow along with Java Module (How to create an Instance of a Class and Invoke Methods) using DataWeave expressions.
  • The Choice Router Control, dynamically routes messages based on message payload or properties to the target. It also adds conditional programming to a message flow, similar to an if/then/else code block in programming.
  • A Choice Router Control uses expressions to evaluate the content of a message. Then it routes the message to one of the routing options within its scope.
  • It directs messages to the first routing option in the scope that matches the routing configurations (evaluates to true).
  • If none of expressions evaluate to true, the Choice Router Control directs the message to the default (else) route. We will see in following working tutorial.

MuleSoft Application Overview

  • In this working tutorial we will implement Choice Router with Java Module.
  • For Java Module integration we will create Java Classes for different operations.
  • It will accept HTTP Request with queryParams -> #[attributes.queryParams.operation] and will return response “Successfully Routed to Flow.”
mulesoft choice router control flow architecture

Basically, we are integrating Choice Router Control with Java Module in message flow.

Technology Stack

Anypoint Studio 7.4.2
Mule Server 4.2.2 EE
Java 1.8
Maven 3.5.0
Connectors: HTTP Listener v1.5.11, Choice Router, Logger, Set Variable, Java Module

Prerequisites : Setup MuleSoft (Mule 4), Maven 3.5 and JDK 1.8 on Windows OS

We need Maven, JDK 1.8 and Mule 4 for running our application. Hence, first of all we need to setup MuleSoft (Mule 4), Maven 3.5 and JDK 1.8 on Windows OS as below.

Configure JDK, Maven and Mule Studio on Windows OS

Follow below steps for configuring JDK, Maven and Mule Anypoint Studio on Windows OS.

Step 1. First install JDK 1.8
Step 2. Add the Java_Home/bin directory to your system’s PATH.
Step 3. After downloading Maven, extract it to a drive.
Step 4. Add the M2_Home/bin directory to your system’s PATH.
Step 5. Download and extract Mule Studio to a drive.
Step 6. Now start Mule Studio by clicking on AnypointStudio exe icon in the folder /AnypointStudio
Step 7. Once started, close the startup page
Step 8. In Mule Studio, go to Window -> Preferences. Expand Java, then click on Installed JREs. Add JDK 1.8 and select it. In expanded Java, click on Compiler and select the compiler level as 1.8
Step 9. Now expand Anypoint Studio and click on Maven Settings. Then select appropriate Maven installation home directory using Browse button.
Step 10. If you want you can input Default groupId for new projects, it will save your time every time when you want to create a new project.

Create MuleSoft project in Mule Studio

Step 1. In Anypoint Studio, go to File -> New -> Mule Project
Step 2. Input Project Name: mule-choice-control-flow-example, Runtime is by default selected, tick on Use Maven; here the artifactId is automatically picked up from the Project Name, the Group Id are picked up from the Default groupId for new projects and version is also a default value.
Step 3. Click Next and verify the JDK, mainly select Use default JRE(e.g. currently ‘zulu8’)
Step 4. Click on Next and click on Finish.

MuleSoft Application Project Structure

Application Project Structure would be looked like as below.

MuleSoft Application Project Structure

Maven File: pom.xml

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
	<modelVersion>4.0.0</modelVersion>

	<groupId>com.example</groupId>
	<artifactId>mule-choice-flow-control-example</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>mule-application</packaging>

	<name>mule-choice-control-flow-example</name>

    <properties>
		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>

		<app.runtime>4.2.2</app.runtime>
		<mule.maven.plugin.version>3.3.5</mule.maven.plugin.version>
	</properties>

	<build>
		<plugins>
			<plugin>
				<groupId>org.mule.tools.maven</groupId>
				<artifactId>mule-maven-plugin</artifactId>
				<version>${mule.maven.plugin.version}</version>
				<extensions>true</extensions>
				<configuration>
				</configuration>
			</plugin>
		<plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>3.7.0</version>
                <configuration>
                    <compilerArgs>
                        <args>-parameters</args>
                    </compilerArgs>
                </configuration>
            </plugin>
        </plugins>
	</build>

	<dependencies>
        <dependency>
            <groupId>org.mule.connectors</groupId>
            <artifactId>mule-http-connector</artifactId>
            <version>1.5.11</version>
            <classifier>mule-plugin</classifier>
        </dependency>
        <dependency>
            <groupId>org.mule.connectors</groupId>
            <artifactId>mule-sockets-connector</artifactId>
            <version>1.1.5</version>
            <classifier>mule-plugin</classifier>
        </dependency>
		<dependency>
            <groupId>org.mule.module</groupId>
            <artifactId>mule-java-module</artifactId>
            <version>1.2.5</version>
            <classifier>mule-plugin</classifier>
        </dependency>
    </dependencies>

	<repositories>
          <repository>
            <id>anypoint-exchange-v2</id>
            <name>Anypoint Exchange</name>
            <url>https://maven.anypoint.mulesoft.com/api/v2/maven</url>
            <layout>default</layout>
        </repository>
        <repository>
            <id>mulesoft-releases</id>
            <name>MuleSoft Releases Repository</name>
            <url>https://repository.mulesoft.org/releases/</url>
            <layout>default</layout>
        </repository>
    </repositories>
    <pluginRepositories>
        <pluginRepository>
            <id>mulesoft-releases</id>
            <name>mulesoft release repository</name>
            <layout>default</layout>
            <url>https://repository.mulesoft.org/releases/</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>

</project>

MuleSoft Java Components

Create below classes which we will use as Java Components in Message Flow.

Routing Message to the “RouteToFile” Java Component

We need to create RouteToFile.java with send(String payload) method as below.

package com.the.basic.tech.info;
public class RouteToFile {
	public String send(String payload) {
		return payload + " Successfully Routed to File Choice Flow.";
	}
}

Routing Message to the “RouteToDatabase” Java Component

We need to create RouteToDatabase.java with send(String payload) method as below.

package com.the.basic.tech.info;
public class RouteToDatabase {
	public String send(String payload) {
		return payload + " Successfully Routed to Database Choice Flow.";
	}
}

Routing Message to the “RouteToQueue” Java Component

We need to create RouteToQueue.java with send(String payload) method as below.

package com.the.basic.tech.info;
public class RouteToQueue {
	public String send(String payload) {
		return payload + " Successfully Routed to Queue Choice Flow.";
	}
}

How to Create an Instance of a Class in MuleSoft Message Flow

We need to integrate Java Components in our MuleSoft Message Flow as below.

<java:new class="com.the.basic.tech.info.RouteToFile" constructor="RouteToFile()" target="routeToFile" />
<java:new class="com.the.basic.tech.info.RouteToDatabase" constructor="RouteToDatabase()" target="routeToDatabase" />
<java:new class="com.the.basic.tech.info.RouteToQueue" constructor="RouteToQueue()" target="routeToQueue" />

How to Invoke Methods of a Class in Mule Message Flow

Once Java Components are instantiated, we can invoke methods and pass argument transformation in Mule Message Flow as below.

<java:invoke instance="#[vars.routeToFile]" class="com.the.basic.tech.info.RouteToFile" method="send(String)" target="routeToFileReturn">
 <java:args>#[{
		payload: vars.operation
	     }]
 </java:args>
</java:invoke>
<logger level="INFO" doc:name="Logger" doc:id="8ffd3719-d9ac-442e-9e5c-a44d6ec155d2" message="#[vars.routeToFileReturn]" />

<java:invoke instance="#[vars.routeToDatabase]" class="com.the.basic.tech.info.RouteToDatabase" method="send(String)" target="routeToDatabaseReturn">
 <java:args>#[{
		payload: vars.operation
	     }]
 </java:args>
</java:invoke>
<logger level="INFO" doc:name="Logger" doc:id="c8ca19ae-29d7-4a65-a24e-0d069d01974f" message="#[vars.routeToDatabaseReturn]" />

<java:invoke instance="#[vars.routeToQueue]" class="com.the.basic.tech.info.RouteToQueue" method="send(String)" target="routeToQueueReturn">
 <java:args>#[{
	        payload: vars.operation
	     }]
 </java:args>
</java:invoke>
<logger level="INFO" doc:name="Logger" doc:id="2b6a5a9f-e8e5-4359-8c27-79a4ac4b00d8" message="#[vars.routeToQueueReturn]" />

Mule Message Flow: mule-choice-control-flow-example.xml

The complete mule message flow xml file would be looked like. Try to focus on queryParam parsing from request, logger and java modules java:new, java:invoke and java:args expressions.

<?xml version="1.0" encoding="UTF-8"?>

<mule xmlns:java="http://www.mulesoft.org/schema/mule/java" xmlns:ee="http://www.mulesoft.org/schema/mule/ee/core" xmlns:http="http://www.mulesoft.org/schema/mule/http"
	xmlns="http://www.mulesoft.org/schema/mule/core" xmlns:doc="http://www.mulesoft.org/schema/mule/documentation" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xsi:schemaLocation="
http://www.mulesoft.org/schema/mule/http http://www.mulesoft.org/schema/mule/http/current/mule-http.xsd http://www.mulesoft.org/schema/mule/core http://www.mulesoft.org/schema/mule/core/current/mule.xsd
http://www.mulesoft.org/schema/mule/ee/core http://www.mulesoft.org/schema/mule/ee/core/current/mule-ee.xsd
http://www.mulesoft.org/schema/mule/java http://www.mulesoft.org/schema/mule/java/current/mule-java.xsd">
	<http:listener-config name="HTTP_Listener_config" doc:name="HTTP Listener config" doc:id="d1a31495-0588-4f00-9b22-dff6fb94f515">
		<http:listener-connection host="0.0.0.0" port="8089" />
	</http:listener-config>
	<flow name="mule-choice-control-flow-example" doc:id="e725df65-55a1-4059-856b-b368d00baa20">
		<http:listener config-ref="HTTP_Listener_config" doc:name="Listener" doc:id="141762a3-a6c8-4c5f-a212-5e11a3f278f1" path="/" />
		<set-variable variableName="operation" value="#[attributes.queryParams.operation]" doc:name="Set Variable" doc:id="86a17c8e-f64e-4614-9487-389cd7afa1aa" />

		<logger level="INFO" doc:name="Logger" doc:id="d91464e9-1e32-4450-b198-e13caf1e0f77" message="#[vars.operation]" />
		<choice doc:name="Choice">
			<when expression="#[vars.operation=='file']">
				<java:new class="com.the.basic.tech.info.RouteToFile" constructor="RouteToFile()" target="routeToFile" />
				<java:invoke instance="#[vars.routeToFile]" class="com.the.basic.tech.info.RouteToFile" method="send(String)" target="routeToFileReturn">
					<java:args>#[{
						payload: vars.operation
						}]
					</java:args>
				</java:invoke>
				<logger level="INFO" doc:name="Logger" doc:id="8ffd3719-d9ac-442e-9e5c-a44d6ec155d2" message="#[vars.routeToFileReturn]" />
				<set-payload value="Successfully Routed to File Flow Value" doc:name="File Operation" doc:id="5f27cb93-36a3-4b48-af4b-62dceadb0fb5" />
			</when>
			<when expression="#[(vars.operation=='db' or vars.operation=='database')]">
				<java:new class="com.the.basic.tech.info.RouteToDatabase" constructor="RouteToDatabase()" target="routeToDatabase" />
				<java:invoke instance="#[vars.routeToDatabase]" class="com.the.basic.tech.info.RouteToDatabase" method="send(String)" target="routeToDatabaseReturn">
					<java:args>#[{
						payload: vars.operation
						}]
					</java:args>
				</java:invoke>
				<logger level="INFO" doc:name="Logger" doc:id="c8ca19ae-29d7-4a65-a24e-0d069d01974f" message="#[vars.routeToDatabaseReturn]" />
				<set-payload value="Successfully Routed to Database Flow Value." doc:name="Database Operation" doc:id="b8fcef0c-8c25-42b6-af77-d3b49052ad10" />
			</when>
			<when expression="#[vars.operation=='queue']">
				<java:new class="com.the.basic.tech.info.RouteToQueue" constructor="RouteToQueue()" target="routeToQueue" />
				<java:invoke instance="#[vars.routeToQueue]" class="com.the.basic.tech.info.RouteToQueue" method="send(String)" target="routeToQueueReturn">
					<java:args>#[{
						payload: vars.operation
						}]
					</java:args>
				</java:invoke>
				<logger level="INFO" doc:name="Logger" doc:id="2b6a5a9f-e8e5-4359-8c27-79a4ac4b00d8" message="#[vars.routeToQueueReturn]" />
				<set-payload value="Successfully Routed to Queue Flow Value." doc:name="Queue Operation" doc:id="776c7acb-3aab-4c3a-aa3a-7ca4425234c0" />
			</when>
			<otherwise>
				<set-payload value="This is an Invalid Operation. Try for file, database or queue Operations." doc:name="Invalid Operation" doc:id="ccbb476e-4ab6-4812-8c1f-f8953f1129d6" />
			</otherwise>
		</choice>
	</flow>
</mule>
Mule Message Flow

How to run MuleSoft application on runtime (Mule 4)

Just Right click on Mule Message Flow: mule-choice-control-flow-example and go to Run as -> Mule Application

It will launch Mule 4 runtime instance and application will be deployed on this.

Mule Application Deploy and Run

MuleSoft Application Logs & Test

MuleSoft Application Logs
MULE_HOME is set to D:\Software\AnypointStudio\plugins\org.mule.tooling.server.4.2.2.ee_7.3.5.202001031809\mule
MULE_BASE is set to D:\Software\AnypointStudio\plugins\org.mule.tooling.server.4.2.2.ee_7.3.5.202001031809\mule
--> Wrapper Started as Console
Launching a JVM...
Starting the Mule Container...
WrapperManager: Initializing...

Running Mule in testing mode

INFO  2021-07-30 19:35:35,053 [WrapperListener_start_runner] org.mule.runtime.core.internal.logging.LogUtil: 
**********************************************************************
*                                                                    *
*                         (((((((((((((((((((                        *
*                     (((((                 ((((#                    *
*                  &(((                        *(((                  *
*                &(((                             (((                *
*               (((     (((%               (((#     (((              *
*              ((     (((((((             (((((((    (((             *
*             ((     (((((((((           (((((((((     ((            *
*            ((    #(((((((((((        #(((((((((((    (((           *
*           #((    ((((((((((((((     ((((((((((((((    ((           *
*           ((    ((((((  /(((((((   (((((((  /((((((    ((          *
*           ((    ((((((    (((((((&(((((((    ((((((    ((          *
*           ((    (((((      ((((((((((((*     ((((((    ((          *
*           ((    ((((((      *(((((((((       ((((((    ((          *
*           ((    ((((((        (((((((        ((((((   (((          *
*            ((    ((((((                     ((((((    ((           *
*            ((#    ((((((#                 (((((((    ((            *
*             ((#    ((((((((             ((((((((    (((            *
*              (((    (((((((              (((((     ((.             *
*                ((      (((               (((     #((               *
*                 /((                            (((                 *
*                    (((                      &(((                   *
*                      *((((&             &((((                      *
*                           ((((((((((((((/                          *
*                                                                    *
*    ___  ___      _        ______            _   _                  *
*    |  \/  |     | |       | ___ \          | | (_)                 *
*    | .  . |_   _| | ___   | |_/ /   _ _ __ | |_ _ _ __ ___   ___   *
*    | |\/| | | | | |/ _ \  |    / | | | '_ \| __| | '_ ` _ \ / _ \  *
*    | |  | | |_| | |  __/  | |\ \ |_| | | | | |_| | | | | | |  __/  *
*    \_|  |_/\__,_|_|\___|  \_| \_\__,_|_| |_|\__|_|_| |_| |_|\___|  *
*                                                                    *
*                                                                    *
* Mule Runtime and Integration Platform                              *
* Version: 4.2.2 Build: e790fb3a                                     *
* MuleSoft, Inc.                                                     *
* For more information go to                                         *
* https://www.mulesoft.com/platform/soa/mule-esb-enterprise          *
*                                                                    *
* Server started: 7/30/21 7:35 PM                                    *
* JDK: 1.8.0_212 (mixed mode)                                        *
INFO  2021-07-30 19:36:08,274 [WrapperListener_start_runner] org.mule.runtime.core.internal.logging.LogUtil: 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ Starting app 'mule-choice-control-flow-example'                              +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
INFO  2021-07-30 19:36:08,275 [WrapperListener_start_runner] [event: ] org.mule.runtime.core.internal.util.queue.QueueXaResourceManager: Starting ResourceManager
INFO  2021-07-30 19:36:08,275 [WrapperListener_start_runner] [event: ] org.mule.runtime.core.internal.util.queue.QueueXaResourceManager: Started ResourceManager
INFO  2021-07-30 19:36:08,302 [WrapperListener_start_runner] [event: ] org.mule.runtime.core.privileged.lifecycle.AbstractLifecycleManager: Starting Bean: org.mule.runtime.module.extension.internal.runtime.config.ConfigurationProviderToolingAdapter-HTTP_Listener_config
INFO  2021-07-30 19:36:08,374 [WrapperListener_start_runner] [event: ] org.mule.runtime.core.internal.construct.FlowConstructLifecycleManager: Starting flow: mule-choice-control-flow-example
INFO  2021-07-30 19:36:09,070 [WrapperListener_start_runner] [event: ] org.mule.runtime.core.privileged.lifecycle.AbstractLifecycleManager: Starting Bean: listener
INFO  2021-07-30 19:36:09,075 [WrapperListener_start_runner] [event: ] org.mule.runtime.core.internal.logging.LogUtil: 
**********************************************************************
* Application: mule-choice-control-flow-example                      *
* OS encoding: UTF-8, Mule encoding: UTF-8                           *
*                                                                    *
**********************************************************************
INFO  2021-07-30 19:36:09,077 [WrapperListener_start_runner] org.mule.runtime.core.internal.logging.LogUtil: 
**********************************************************************
* Started app 'mule-choice-control-flow-example'                     *
* Application plugins:                                               *
*  - Java : 1.2.5                                                    *
*  - Sockets : 1.1.5                                                 *
*  - HTTP : 1.5.11                                                   *
**********************************************************************
INFO  2021-07-30 19:36:09,112 [WrapperListener_start_runner] org.mule.runtime.core.internal.logging.LogUtil: 
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
+ Mule is up and kicking (every 5000ms)                                        +
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
INFO  2021-07-30 19:36:09,134 [WrapperListener_start_runner] org.eclipse.jetty.server.AbstractConnector: Started ServerConnector@35113b36{HTTP/1.1,[http/1.1]}{0.0.0.0:49941}
INFO  2021-07-30 19:36:09,138 [WrapperListener_start_runner] org.mule.runtime.core.internal.logging.LogUtil: 
**********************************************************************
*              - - + DOMAIN + - -               * - - + STATUS + - - *
**********************************************************************
* default                                       * DEPLOYED           *
**********************************************************************

*******************************************************************************************************
*            - - + APPLICATION + - -            *       - - + DOMAIN + - -       * - - + STATUS + - - *
*******************************************************************************************************
* mule-choice-control-flow-example              * default                        * DEPLOYED           *
*******************************************************************************************************

MuleSoft Application Testing : Hit On Browser

File Operation (http://localhost:8089/?operation=file)

Mule Http Request - Rest API

Database/db Operation (http://localhost:8089/?operation=database)

Mule Http Request - Rest API

Queue Operation (http://localhost:8089/?operation=queue)

Mule Http Request - Rest API

Unknown Operation (http://localhost:8089/?operation=xpath)

Mule Http Request - Rest API
INFO  2021-07-30 19:36:09,138 [WrapperListener_start_runner] org.mule.runtime.core.internal.logging.LogUtil: 
**********************************************************************
*              - - + DOMAIN + - -               * - - + STATUS + - - *
**********************************************************************
* default                                       * DEPLOYED           *
**********************************************************************

*******************************************************************************************************
*            - - + APPLICATION + - -            *       - - + DOMAIN + - -       * - - + STATUS + - - *
*******************************************************************************************************
* mule-choice-control-flow-example              * default                        * DEPLOYED           *
*******************************************************************************************************

INFO  2021-07-30 19:41:59,552 [[MuleRuntime].cpuLight.08: [mule-choice-control-flow-example].mule-choice-control-flow-example.CPU_LITE @27bca311] [event: 13b4f780-f140-11eb-892e-a44cc84ce10c] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: file

INFO  2021-07-30 19:41:59,747 [[MuleRuntime].io.03: [mule-choice-control-flow-example].mule-choice-control-flow-example.BLOCKING @332c4d5c] [event: 13b4f780-f140-11eb-892e-a44cc84ce10c] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: file Successfully Routed to File Choice Flow.

INFO  2021-07-30 19:45:12,779 [[MuleRuntime].cpuLight.08: [mule-choice-control-flow-example].mule-choice-control-flow-example.CPU_LITE @27bca311] [event: 8e03d970-f140-11eb-892e-a44cc84ce10c] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: database

INFO  2021-07-30 19:45:12,848 [[MuleRuntime].io.03: [mule-choice-control-flow-example].mule-choice-control-flow-example.BLOCKING @332c4d5c] [event: 8e03d970-f140-11eb-892e-a44cc84ce10c] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: database Successfully Routed to Database Choice Flow.
INFO  2021-07-30 19:46:00,648 [[MuleRuntime].cpuLight.08: [mule-choice-control-flow-example].mule-choice-control-flow-example.CPU_LITE @27bca311] [event: aa8bc620-f140-11eb-892e-a44cc84ce10c] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: queue

INFO  2021-07-30 19:46:00,671 [[MuleRuntime].io.03: [mule-choice-control-flow-example].mule-choice-control-flow-example.BLOCKING @332c4d5c] [event: aa8bc620-f140-11eb-892e-a44cc84ce10c] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: queue Successfully Routed to Queue Choice Flow.
INFO  2021-07-30 19:46:49,020 [[MuleRuntime].cpuLight.08: [mule-choice-control-flow-example].mule-choice-control-flow-example.CPU_LITE @27bca311] [event: c7610f80-f140-11eb-892e-a44cc84ce10c] org.mule.runtime.core.internal.processor.LoggerMessageProcessor: xpath

Thank you for reading 🙂