Improve MuleSoft Builds with a Parent POM

Managing builds in MuleSoft projects can quickly get complicated — especially when we’re working across multiple APIs, integrations, and environments. Each project ends up with its own pom.xml, dependency versions, plugins, and configurations, which often leads to duplication, inconsistencies, and a lot of manual effort to keep everything in sync.
That’s where a Parent POM structure comes in. By centralizing common dependencies, plugins, and build configurations in a single parent pom.xml, we can simplify project setup, enforce consistency across teams, and reduce maintenance overhead. This approach not only makes builds cleaner but also helps streamline CI/CD pipelines, making the overall development lifecycle more efficient.
In this article, I’ll walk through how to design a parent POM for MuleSoft projects, the benefits it brings, and some best practices to keep in mind.
- Creating a Parent POM:
Just create a new folder (mulesoft-parent), add a pom.xml file inside it,
and also add a .gitignore file if you want to ignore anything.
We don’t have to start from scratch. The easiest way is to copy one of your existing application POMs and then update it for the parent setup.
- Change the packaging type to
pom
<packaging>pom</packaging>
- If your organization has multiple business groups, use the Org ID or Business Group ID as the
groupId.
Here’s how it will look:
<name>parent-pom</name>
<description>A parent POM project for shared configuration and documentation</description>
<groupId>xxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxx</groupId>
<artifactId>crh-solution-selling-parent-pom</artifactId>
<version>1.0.6</version>
<packaging>pom</packaging>
We can also define common properties here, which we’ll reuse later.
Make sure to set <type> as custom:
<properties>
<!-- Always keep type as custom for Mule applications -->
<type>custom</type>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<anypoint.base_uri>https://anypoint.mulesoft.com/</anypoint.base_uri>
<anypoint.analytics_base_uri>https://analytics-ingest.anypoint.mulesoft.com/</anypoint.analytics_base_uri>
<!-- Mule Deployment Versions -->
<app.runtime>4.9-e-java17</app.runtime>
<api.version>v1</api.version>
<!-- Mule Plugin Versions -->
<mule.maven.plugin.version>4.3.1</mule.maven.plugin.version>
<maven-clean-plugin-version>3.2.0</maven-clean-plugin-version>
<munit.coverage.failBuild>true</munit.coverage.failBuild>
<!-- Dependencies versions -->
<munit.version>3.3.2</munit.version>
<mule-secure-configuration-property-module-version>1.2.7</mule-secure-configuration-property-module-version>
<assertions-version>1.0.2</assertions-version>
<reference-global-error-handling-version>1.0.12</reference-global-error-handling-version>
</properties>
✅ type=custom tells Mule that this is a deployable Mule app, not an API spec, policy, or template — avoiding conflicts during build/deploy.
This <build> section in our pom.xml is where all the plugins for our MuleSoft project are defined.
<build>
<plugins>
<plugin>
<groupId>org.mule.tools.maven</groupId>
<artifactId>exchange-mule-maven-plugin</artifactId>
<version>0.0.23</version>
<inherited>false</inherited>
<executions>
<execution>
<id>validate</id>
<phase>validate</phase>
<goals>
<goal>exchange-pre-deploy</goal>
</goals>
</execution>
<execution>
<id>deploy</id>
<phase>deploy</phase>
<goals>
<goal>exchange-deploy</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>${maven-clean-plugin-version}</version>
</plugin>
<plugin>
<groupId>org.mule.tools.maven</groupId>
<artifactId>mule-maven-plugin</artifactId>
<version>${mule.maven.plugin.version}</version>
<extensions>true</extensions>
<configuration>
<cloudHubDeployment>
<uri>${anypoint.base_uri}</uri>
<muleVersion>${app.runtime}</muleVersion>
<connectedAppGrantType>client_credentials</connectedAppGrantType>
<connectedAppClientId>${anypoint.connectedAppClientId}</connectedAppClientId>
<connectedAppClientSecret>${anypoint.connectedAppClientSecret}</connectedAppClientSecret>
<applicationName>${appname}</applicationName>
<businessGroupId>${anypoint.businessgroupId}</businessGroupId>
<environment>${anypoint.environment}</environment>
<workers>${mule.workers}</workers>
<workerType>${mule.workerType}</workerType>
<region>${anypoint.region}</region>
<deploymentTimeout>2000000</deploymentTimeout>
<objectStoreV2>true</objectStoreV2>
<properties>
<anypoint.platform.client_id>${anypoint.platform.client_id}</anypoint.platform.client_id>
<anypoint.platform.client_secret>${anypoint.platform.client_secret}</anypoint.platform.client_secret>
<env>${environment-name}</env>
<mule.secure.key>${mule.secure.key}</mule.secure.key>
<anypoint.platform.base_uri>${anypoint.base_uri}</anypoint.platform.base_uri>
<anypoint.platform.analytics_base_uri>${anypoint.analytics_base_uri}</anypoint.platform.analytics_base_uri>
</properties>
</cloudHubDeployment>
<classifier>mule-application</classifier>
</configuration>
</plugin>
<plugin>
<groupId>com.mulesoft.munit.tools</groupId>
<artifactId>munit-maven-plugin</artifactId>
<version>${munit.version}</version>
<executions>
<execution>
<id>test</id>
<phase>test</phase>
<goals>
<goal>test</goal>
<goal>coverage-report</goal>
</goals>
</execution>
</executions>
<configuration>
<coverage>
<runCoverage>true</runCoverage>
<failBuild>${munit.coverage.failBuild}</failBuild>
<formats>
<format>html</format>
<format>console</format>
</formats>
<requiredApplicationCoverage>80</requiredApplicationCoverage>
<requiredResourceCoverage>80</requiredResourceCoverage>
<requiredFlowCoverage>80</requiredFlowCoverage>
</coverage>
</configuration>
</plugin>
</plugins>
</build>
✅ In short:
exchange-mule-maven-plugin → handles Exchange assets.
maven-clean-plugin → cleans build.
mule-maven-plugin → deploys app to CloudHub.
munit-maven-plugin → runs tests & coverage validation.
✅ Finally, make sure your pom.xml is complete. This means it should have all the required dependencies, repositories, plugin repositories, profiles, and distribution management sections properly set up. These are crucial because they ensure that your builds run smoothly, plugins resolve correctly, and deployments happen without surprises.
Repositories & Plugin Repositories → to pull Mule and Exchange assets
Profiles → to manage app naming across
dev,qa,uat,prodDistribution Management → to publish to Anypoint Exchange
🔑 Note: In the dependencies section, only keep the common dependencies that are shared across multiple applications. Avoid adding dependencies that are used only in a single app otherwise, they will get pulled into every application unnecessarily, creating bloat and possible conflicts.
🚀 Deploy to Exchange
Now that the parent POM is ready, it’s time to publish it to Anypoint Exchange so that all applications in your organization can use it.
Open the terminal and run the following command:
mvn clean deploy
✅ Important: Before running this command, make sure you have a properly configured settings.xml file with your Anypoint credentials. This file is required so Maven can authenticate and push the artifact to Exchange successfully.
👉 If your application runs into any issues, you can refer to the following articles for guidance:
409 Conflict → Salesforce Help Article
412 Precondition Failed → Salesforce Help Article
Artifact could not be resolved → Salesforce Help Article
Asset already exists with this version → Update the
<version>in yourparent-pom.xmland re-deploy.
✅ Import the Parent POM in Mule Application
Once the parent POM is successfully deployed to Anypoint Exchange, we can import it into our Mule application by adding the following section in our application’s pom.xml:
<parent>
<groupId>xxxxxxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxxxxx</groupId>
<artifactId>parent-pom</artifactId>
<version>1.0.6</version>
</parent>
This will ensure your Mule application inherits all the common configuration and dependencies defined in the parent POM.
Source Code & Hands-On Examples
You can check out the complete implementation of both the Parent POM and the sample Mule application that consumes it:
MuleSoft Parent POM — see all shared configurations, dependencies, repo setups, and environment profiles
https://github.com/pradeep-kargwal/mulesoft-parentHello-World Mule Application — a live Mule app that inherits from the parent POM, demonstrating how everything ties together
https://github.com/pradeep-kargwal/hello-world-app