Last Updated on 15/09/2022 by Patryk Bandurski
Reusability is essential to deliver functionality quicker and more consistently. I wrote about reusing DataWeave code in Modules, and also reusing RAML using API Fragments. Today I focus on sharing common logic encapsulated within the (private) flow or subflow. I will create a standard MuleSoft application and amend it to make it truly Common Module. You will see how easy it is to prepare a reusable mule module and make it available on Anypoint Exchange as a brand-new asset.
This is an updated article to match the newest approach.
Assets on Anypoint Exchange
You are used to seeing API specifications, API fragments, and maybe even custom policies on Anypoint Exchange. This is the first place where we look for assets that we can potentially reuse. So you may ask yourself, how about my reusable logic encapsulated in flow/subflows? We can do the same! We can publish the MuleSoft project with flows on Anypoint Exchange as a MuleSoft Plugin that can be easily used in your projects by adding a dependency to the pom.xml file. Down below, you can see what we are aiming to achieve today.
Project creation
First, we need to create a new maven project. We can start by creating a new empty Mule project in Anypoint Studio – like you regularly do. Then we need to amend the project’s POM file slightly. We can also remove unnecessary files like log4j2.xml and log4j2-test.xml.
pom.xml modification
We need to make a couple of important changes to the pom.xml file. Without them, the project won’t perform its function as a common module. First, add a classifier to the mule-maven-plugin configuration. It will instruct that we are dealing with MuleSoft Plugin.
<plugin>
<groupId>org.mule.tools.maven</groupId>
<artifactId>mule-maven-plugin</artifactId>
<version>${mule.maven.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<classifier>mule-plugin</classifier>
</configuration>
</plugin>
Next, we add the plugin for publishing to Anypoint Exchange. Down below, you can see the plugin as mentioned earlier.
<plugin>
<groupId>org.mule.tools.maven</groupId>
<artifactId>exchange-mule-maven-plugin</artifactId>
<version>${mule.exchange.maven.plugin.version}</version>
</plugin>
New build model
Mule 4 introduced a completely new build model. When you build your project, you should see a jar file instead of a zip in the target library. The filename pattern is as follows:{artifact-id}-{version}-mule-application.jar
Previously it was:{artifact-id}-{version}.zip
As we publish the asset to Anypoint Exchange, we need to add a distribution repository pointing to our Anypoint Platform. So let’s have a look at distributionManagement configuration down below. We have two important parts here. First is id, that identified repository defined in your settings.xml file. This repository should use your credentials for the Anypoint Platform. Secondly, url points to your organization or business group on the Anypoint Platform.
<distributionManagement>
<repository>
<!-- TODO: id identify the repository defined in settings.xml-->
<id>exchange-v3</id>
<name>Anypoint Exchange Repository</name>
<url>https://maven.anypoint.mulesoft.com/api/v3/organizations/${project.groupId}/maven</url>
<layout>default</layout>
</repository>
</distributionManagement>
Last but not least, let’s move to the dependencies. We may need common flows to use MuleSoft modules. Used modules are added in the dependencies section. Instructing the building plugin not to include the modules in the target jar file is important. All needed dependencies should be delivered by consuming the application. I highlighted below the scope that needs to be added with the value provided.
<dependencies>
<dependency>
<groupId>org.mule.connectors</groupId>
<artifactId>mule-http-connector</artifactId>
<version>1.7.1</version>
<classifier>mule-plugin</classifier>
<scope>provided</scope>
</dependency>
</dependencies>
Mule configuration files
Now we are ready to create new mule configuration files with a reusable set of features. It is a good practice to create separate configuration files per feature. For example, logging-related subflows can be stored in the logging.xml file, health check in health.xml, etc. When we have exception handlers for rest/soap services, we may store them in system-layer-error-handling.xml.
You may do it differently if it is easy to read and maintain. It is up to you.
Ready to use common module
You may download the Maven-based project from my GitHub repository and treat it as a template for your common module. To use that project in Anypoint Studio, you need to utilize Import functionality and import it like an ordinary MuleSoft application (Anypoint Studio > Anypoint Studio project from File System)
Deployment
The project needs to be available through Maven. To publish your common module asset to Anypoint Exchange, go to the project’s root folder and invoke the command mvn deploy
Project Usage
To use our awesome features, we first need to load the dependency. How to get it? You can get it from the pom file of your common module application or Anypoint Exchange by clicking the Dependency Snippets button – you can see a sample dependency below.
We need to import configuration files to use reusable flows in our project. We only need to import what we need. This typically is done in the global.xml file on the Global Elements view. Click Create button and then search for Import. You type the name of the file that is present in your jar.
<import doc:name="Import" file="system-layer-error-handling.xml" />
Now you can refer to flows defined in imported files.
When we refer to DataWeave modules, we do it by the import keyword followed by package and file names. Like in the snippet below – work as if the DataWeave scripts were locally in your MuleSoft Application.
%dw 2.0
output application/json skipNullOn="everywhere"
import dwl::json::utils::emptiness_filter
---
emptiness_filter::filterEmptyObjects({})
Details on how to import and use modules are described here.
Summary
It is an easy task to extract common features into a separate project and reuse them across different applications and projects. This is possible by using the maven project. More importantly, we can use the power of Anypoint Exchange and store that asset as a MuleSoft plugin. It makes reusing our module super straightforward.
Setup requires some initial effort, but it pays off later on. I highly recommend doing that for your projects. Then, you can simply extract logging logic, error handling logic, DataWeave modules, health checks, etc.
Munit normally fails with common imported flows. An issue rutime 4.3 and munit
I wrote on Linkedin about my case when munits did not work from GUI, but it works perfectly fine from maven. Did you report an issue to the MuleSoft Support team? Can you share the error message? Maybe I have seen this before. Patryk