How to share reusable code in MuleSoft

Last Updated on 04/05/2021 by Patryk Bandurski

From my point of view, reusability is extremely important to deliver functionality quicker and in a more consistent manner. I wrote about reusing DataWeave code in Modules, also reusing RAML using API Fragments. Today I focus on sharing some common logic, encapsulated within the (private) flow or subflow. In Mule ESB we have a couple of ways to handle that scenario. I will focus on the custom maven project. You will see how easy it is to prepare a reusable mule library.

Common libraries

It is a common practice to create our own common mule libraries. I highly recommend that, as this may not be only reusable for the current project but for others as well. It only depends on that, how generic it is, what we are sharing.

Common features project

We may share custom logic encapsulated within flows/subflows. The same applies to functions that were prepared in DataWeave. In this article, I have described how to create modules. Such files can be attached to our shared project and shared by our custom mule library

Project creation

Mule Common Module Project’s structure

First, we need to create a new maven project. We can start by creating a new empty Mule project in Anypoint Studio. Then we need to amend slightly the project’s POM file. 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 in the POM.xml. Without them, the project won’t perform its function as a common module. First, remove the packaging, we should use the default one.

<packaging>mule-application</packaging>

Next, we should remove plugins and add the plugin for complaining JAVA sources. Down below you can see the aforementioned plugin.

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-complier-plugin</artifactId>
	<version>3.7.0</version>
	<configuration>
		<complierArgs>
			<args>-parameters</args>
		</complierArgs>
	</configuration>
</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. Filename pattern is as follows:
{artifact-id}-{version}-mule-application.jar
Previously it was:
{artifact-id}-{version}.zip

When you build your project with maven-compiler-plugin, content from the mule and resources folder won’t be transferred to the jar file. We need to instruct the maven plugin, that we are interested in content stored in our custom folders. In the build section, you need to add the resources element. Each new folder needs to be mentioned by name. Like in the snippet below:

<resources>
	<resource>
		<directory>src/main/mule</directory>
	</resource>
	<resource>
		<directory>src/main/resources</directory>
	</resource>
	<resource>
		<directory>src/main/java</directory>
	</resource>
</resources>

You can remove section repositories and pluginRepositories. Last but not least let’s move to the dependencies. We may need in common flows to use MuleSoft modules. Used modules are added in the dependencies section. It is important to instruct the building plugin not to include the modules in the target jar file. All needed dependencies should be delivered by consuming the application. Down below I highlighted 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.5.24</version>
			<classifier>mule-plugin</classifier>
			<scope>provided</scope>
		</dependency>
</dependencies>

Support Mule module dependencies

You can remove dependencies with the MuleSoft Modules and your common module will still work. However, in the Anypoint Studio, you start noticing that you can not use the visual editor to create reusable flows. That is why I recommend supporting modules in the POM.xml file in the dependencies section, but like mentioned above always with provided scope.

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. When we have exception handlers for rest/soap services we may store them in system-layer-error-handling.xml, etc.

As long as it is easy to read and maintain , you may do it differently. 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. In order to use that project in Anypoint Studio, you need to use Import functionality and import it like an ordinary MuleSoft application (Anypoint Studio > Anypoint Studio project from File System)

Installation

The project needs to be available through Maven. In order to install your project or project downloaded from my GitHub repository in local maven go to the project’s root folder and invoke the command mvn clean install

Project usage

To use our awesome features, we need first to load the dependency. Therefore go to the pom.file in your Mule application like system API and add the dependency. Down below, you can see the dependency to my common-module stored in the GitHub repository.

<dependency>
	<groupId>com.ambassadorpatryk</groupId>
	<artifactId>common-module</artifactId>
	<version>1.0.0</version>
</dependency>

To find if the dependency has been downloaded, go to Project Libraries in Package Explorer. Then navigate to your library name. In my case that is common-module-1.0.0.jar.

To use reusable flows in our project we need to import configuration files. We only need to import what we need. This typically is done in 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. 

Imporiting system-layer-error-handling.xml reusable file from common-module project
Imporiting system-layer-error-handling.xml reusable file from common-module project
<import doc:name="Import" file="system-layer-error-handling.xml" />

When you save your project, you will be able to refer to flows defined in imported files. 

When we refer to DataWeave modules we do it by the import keyword followed by package name and file name. Like in the snippet below. It means that you have folder src/main/resources/dwl/json/utils in your common module and file emptiness_filter.dwl.

%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 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. This requires some initial setup but it pays off later on. I highly recommend doing that for your projects. You can simply extract logging logic, error handling logic, DataWeave modules, etc.

How to share reusable code in MuleSoft

2 thoughts on “How to share reusable code in MuleSoft

  1. Munit normally fails with common imported flows. An issue rutime 4.3 and munit

    1. 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

Leave a Reply

Your email address will not be published.

Scroll to top