Implementing Parent POM in Mule 4: A Complete Guide

Parent POM (Project Object Model) plays a crucial role in standardizing project configurations and promoting best practices, thereby enhancing the efficiency and maintainability of Mule applications developed using Maven.

In this guide, I’ll walk you through implementing Parent POM in Mule 4 and publishing it to Anypoint Exchange.

Note: I’ll be covering only Parent POM, not BOM. Let me know if you need to learn about BOM.

What is Parent POM?

A Parent POM (Project Object Model) in Mule 4 is like a master instruction manual for building Mule applications. It contains all the standard settings, dependencies, and configurations needed for multiple Mule projects within an organization.

parent-pom-in-mule

Let’s understand with a small example.

Imagine you’re baking different types of cakes, but all cakes need flour, sugar, and eggs. The parent POM is like a recipe book with everyday ingredients and instructions.

Each specific cake recipe (or Mule project) can then build upon this foundation, adding its unique flavour (custom configurations) while still relying on the essential ingredients and instructions the parent POM provides.

So, instead of writing the exact instructions for each cake recipe separately, you have a single recipe book (the parent POM) that ensures consistency, simplifies maintenance, and helps everyone in the kitchen (development team) follow the same baking rules.

To make it easier to follow, we’ve laid out a trail of croissants to guide your way. Whenever you see a 🥐 it means there’s something for you to do.

Prerequisites

Before you begin, ensure you have the following:

Problem Statement

Let’s start by understanding the problem statement and how to leverage Parent POM to solve the problem.

As a development team working on multiple Mule applications within an organization, we encounter challenges in maintaining consistency across project configurations, managing dependencies, and ensuring adherence to best practices.

Without a standardized approach, we face issues with version mismatches, redundant configurations, and difficulties in collaboration and maintenance.

Solution

Implementing a parent POM in Mule 4 can address these challenges effectively. The parent POM is a centralized configuration file that defines standard settings, dependencies, and plugins for all Mule projects within the organization.

Implementing Parent POM in Mule 4

Analysis

🥐 First, identify your integrations’ standard configurations, dependencies, and plugins list.

🥐 Go to MuleSoft release notes and note down the latest connectors versions you will use in your integration projects.

For instance, my integrations will use HTTP Connector, APIKit, Secure Property Placeholder, Salesforce, Object Store, and Anypoint MQ.

HTTP Connector -> 1.9.1
Object Store Connector -> 1.2.2
Salesforce Connector -> 10.19.4
Anypoint MQ Connector -> 4.0.6
Secure Config Module -> 1.2.7
APIKit Module -> 1.10.3

🥐 Open any project’s POM file, and you’ll find the sections below. As these are common across all projects, we can move these configurations, plugins and dependencies to Parent POM.

  • <properties>
  • <build>
  • <dependencies>
  • <repositories>
  • <pluginRepositories>

Parent POM Configuration

🥐 Open any folder and create a file called pom.xml.

🥐 Copy & paste the content below content in your pom.xml.

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    

</project>

Update Root Values

Let’s add the name, artifactId, groupId and other values.

<modelVersion>4.0.0</modelVersion>
<groupId>{add your Anypoint Platform OrgId}</groupId>
<artifactId>parent-pom</artifactId>
<packaging>pom</packaging>
<version>1.0.0</version>
<name>parent-pom</name>

groupId must be your Anypoint Platform Organization ID if you’re deploying Assets to Anypoint Exchange.

If you deploy and manage your Assets in other Artifacts, such as Azure, you can update groupId to anything you wish.

I go with com.<company>.parentpom. Please don’t add your complete company name; make it short. For instance, com.acme.parentpom.

Properties

🥐 Add all the required properties, including connector and module versions.

This is where you can add all the connectors and module versions you intend to use in your integration projects.

Below are the generic properties for all Mule projects, so let’s add them first.

<properties>
        <!--- Generic Properties -->
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <app.runtime>4.5.1</app.runtime>
    <mule.maven.plugin.version>4.1.1</mule.maven.plugin.version>
    <exchange.mule.maven.plugin>0.0.13</exchange.mule.maven.plugin>
</properties>

Make sure to check Java compatibility for the Mule Maven Plugin. Mule Maven 4.1.1 will support Java 8, 11, and 17. Mule Maven 3.8.2will support Java 8.

I use Java 11 with the Maven 3.9.x version, so Mule Maven 4.1.1 will work for me. If you’re using Java 8 and Maven 3.6.3 to 3.8.6, please use Mule Maven 3.8.7.

Refer to Mule Maven release notes for more information.

🥐 Next, add the required Connectors, Modules and Custom Plugin versions.

<properties>
    <!-- Mule Connectors and Modules -->
    <organizationId>{add your Anypoint Platform OrgId}</organizationId>
    <apikit.version>1.10.3</apikit.version>
    <http.connector.version>1.9.1</http.connector.version>
    <amq.connector.version>4.0.6</amq.connector.version>
    <sfdc.connector.version>10.19.4</sfdc.connector.version>
    <mule.secure.config.version>1.2.7</mule.secure.config.version>
    <os.connector.version>1.2.2</os.connector.version>
    <!-- Specifcy Asset Type-->
    <type>custom</type>
    <!-- CloudHub Deployment Properties-->
    <mule.cloudhub.monitoring.enabled>true</mule.cloudhub.monitoring.enabled>
</properties>

Make sure to add type as custom – <type>custom</type>

Build

🥐 In <build> section, define plugin versions and configurations applied globally to all child projects.

It allows you to centralize plugin configurations in a parent POM so that child projects can inherit and use them without explicitly specifying the plugin versions and configurations again.

Add Mule-related Maven plugins, Generic Maven plugins, CloudHub or other deployment target configurations here and Mule extension-related plugins.

These plugins and configurations are generic for all Mule projects, so it is better to add them in pluginManagement section.

There are two plugin configurations:

  1. mule-maven-plugin (required)
  2. munit-maven-plugin (required)
  3. exchange-mule-maven-plugin is required only for Exchange deployment.
<build>
    <pluginManagement>
        <plugins>
            <!-- Mule Maven Plugin and CloudHub Deployment Configuration-->
            <plugin>
                <groupId>org.mule.tools.maven</groupId>
                <artifactId>mule-maven-plugin</artifactId>
                <version>${mule.maven.plugin.version}</version>
                <extensions>true</extensions>
                <configuration>
                    <cloudHubDeployment>
                        <uri>https://anypoint.mulesoft.com</uri>
                        <muleVersion>${mule.app.runtime}</muleVersion>
                        <username>${mule.cloudhub.username}</username>
                        <password>${mule.cloudhub.password}</password>
                        <applicationName>${mule.cloudhub.app.name}</applicationName>
                        <environment>${mule.env}</environment>
                        <region>${mule.region}</region>
                        <workerType>${mule.workerType}</workerType>
                        <workers>${mule.workers}</workers>
                        <objectStoreV2>true</objectStoreV2>
                        <properties>
                            <mule.env>${mule.env}</mule.env>
                            <mule.encryptionKey>${mule.encryptionKey}</mule.encryptionKey>
                            <mule.cloudhub.https.port>${mule.cloudhub.https.port}</mule.cloudhub.https.port>
                            <anypoint.platform.client_id>${mule.cloudhub.env.client.id}</anypoint.platform.client_id>
                            <anypoint.platform.client_secret>${mule.cloudhub.env.client.secret}</anypoint.platform.client_secret>
                            <mule.monitoringEnabled>${mule.cloudhub.monitoring.enabled}</mule.monitoringEnabled>
                            <anypoint.platform.config.analytics.agent.enabled>${mule.cloudhub.monitoring.enabled}</anypoint.platform.config.analytics.agent.enabled>
                        </properties>
                    </cloudHubDeployment>
                    <classifier>mule-application</classifier>
                </configuration>
            </plugin>
            <!-- Mule MUnit 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>
                    <runtimeVersion>${mule.app.runtime}</runtimeVersion>
                    <systemPropertyVariables>
                        <mule.env>munit</mule.env>
                    </systemPropertyVariables>
                    <coverage>
                        <runCoverage>true</runCoverage>
                        <failBuild>true</failBuild>
                        <requiredApplicationCoverage>${munit.testcoverage.app}</requiredApplicationCoverage>
                        <requiredResourceCoverage>${munit.testcoverage.resource}</requiredResourceCoverage>
                        <requiredFlowCoverage>${munit.testcoverage.flow}</requiredFlowCoverage>
                        <formats>
                            <format>console</format>
                            <format>html</format>
                            <format>json</format>
                            <format>sonar</format>
                        </formats>
                    </coverage>
                </configuration>
            </plugin>
            <!-- It's required only for Exchange Deployment-->
            <plugin>
                <groupId>org.mule.tools.maven</groupId>
                <artifactId>exchange-mule-maven-plugin</artifactId>
                <version>${exchange.mule.maven.plugin}</version>
                <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>
        </plugins>
    </pluginManagement>
</build>

You must pass the CloudHub Deployment properties in Runtime through the CI/CD pipeline.

Distribution Management

🥐 In distributionManagement section, specify where the built artefacts should be deployed. Typically, it’s used in the parent POM file to define the deployment repositories, and child projects inherit these settings.

In our case, we will deploy artefacts to Anypoint Exchnage, so add Exchnage repository details.

<distributionManagement>
    <repository>
        <id>Exchange3</id>
        <name>Anypoint Platform Exchange Repository</name>
        <url>https://maven.anypoint.mulesoft.com/api/v3/organizations/c09b2cb2-1258-47d1-a4d1-41a9f7698f34/maven</url>
        <layout>default</layout>
    </repository>
</distributionManagement>

Note down the Id (Exchange3) because you should use the same ID in your settings.xml, or else, you’ll end up with MojoFailureException

The above URL is different for the EU and Government cloud. For more information, visit MuleSoft documentation.

Dependency Management

🥐 In dependencyManagement section, add common dependencies’ versions and configurations which are generic to all Mule projects.

It allows you to specify the versions of dependencies used in your project without including them in your dependency list.

Can you guess the common dependencies?

  • Munit
  • Secure Properties Module

If you have any custom plugins, such as JSON Logger, which is required for all Mule projects, you can include them as well.

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.mulesoft.munit</groupId>
            <artifactId>munit-runner</artifactId>
            <version>${munit.version}</version>
            <classifier>mule-plugin</classifier>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.mulesoft.munit</groupId>
            <artifactId>munit-tools</artifactId>
            <version>${munit.version}</version>
            <classifier>mule-plugin</classifier>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.mulesoft.modules</groupId>
            <artifactId>mule-secure-configuration-property-module</artifactId>
            <version>${mule.secure.config.version}</version>
            <classifier>mule-plugin</classifier>
        </dependency>
    </dependencies>
</dependencyManagement>

Don’t add project-specific dependencies because it’s a centralized Parent POM; whatever you define here will be added to your Project. For instance, if you add Salesforce dependencies, they will be added to all your Projects (Exp, Process and Sys).

Repositories

Repositories are used to specify locations from where Maven can retrieve project dependencies. These dependencies typically include libraries and frameworks your project relies on for compilation, testing, and execution.

Maven searches these repositories to download JAR files and other artefacts needed for the build process.

Examples of regular repositories include Maven Central Repository and other public or private repositories hosting Java libraries and dependencies.

🥐 In repositories section, add repos such as Exchange v3, Mule EE, etc.,

<repositories>
    <!--<repository>
                        <id>mulesoft-artifacts</id>
                        <url>https://pkgs.dev.azure.com/effinium/{azure-org-id}/_packaging/mulesoft-artifacts/maven/v1</url>
                        <releases>
                                <enabled>true</enabled>
                        </releases>
                        <snapshots>
                                <enabled>true</enabled>
                        </snapshots>
                </repository> -->
    <repository>
        <id>Exchange3</id>
        <name>Anypoint Exchange</name>
        <url>https://maven.anypoint.mulesoft.com/api/v3/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>
    <!--<repository>
                        <id>mulesoft-ee</id>
                        <name>MuleSoft Enterprise Repository</name>
                        <url>https://repository.mulesoft.org/nexus-ee/content/repositories/releases-ee/</url>
                        <layout>default</layout>
                        <releases>
                                <enabled>true</enabled>
                        </releases>
                        <snapshots>
                                <enabled>true</enabled>
                        </snapshots>
                </repository> -->
</repositories>

I have also included the Azure Artifect repository for your reference. For Exchange deployment, you can ignore this repo.

If you don’t have a licence for enterprise, please remove the Nexus repo mulesoft-ee reference because it requires a username and password.

Plugin Repositories

Plugin repositories are explicitly used to specify locations from where Maven can retrieve plugins necessary for building or managing the project.

These plugins extend Maven’s functionality and are often used for tasks such as compiling code, packaging applications, running tests, and deploying artefacts.

Maven searches these repositories to download plugin artefacts required for executing build goals defined in the project’s lifecycle.

The main difference between Repositories and Plugin Repositories is regular repositories provide dependencies needed by your project. In contrast, plugin repositories provide plugins needed by Maven to perform various build tasks on your project.

🥐 In pluginRepositories section, add plugin repos such as Mule Nexus, Mule Public, etc.

    <pluginRepositories>
        <pluginRepository>
            <id>mule-public</id>
            <url>https://repository.mulesoft.org/nexus/content/repositories/releases</url>
        </pluginRepository>
        <pluginRepository>
            <id>mulesoft-release</id>
            <name>mulesoft release repository</name>
            <layout>default</layout>
            <url>https://repository.mulesoft.org/releases/</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </pluginRepository>
        <!--<pluginRepository>
                        <id>mulesoft-ee</id>
                        <name>MuleSoft Enterprise Repository</name>
                        <url>https://repository.mulesoft.org/nexus-ee/content/repositories/releases-ee/</url>
                        <layout>default</layout>
                        <releases>
                                <enabled>true</enabled>
                        </releases>
                        <snapshots>
                                <enabled>true</enabled>
                        </snapshots>
                </pluginRepository> -->
    </pluginRepositories>

If you don’t have a licence for enterprise, please remove the Nexus repo mulesoft-ee reference because it requires a username and password.

Complete Parent POM

Here is our complete Parent POM file.

<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>{add your Anypoint Platform OrgId}</groupId>
    <artifactId>parent-pom</artifactId>
    <packaging>pom</packaging>
    <version>1.0.0</version>
    <name>parent-pom</name>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <app.runtime>4.5.1</app.runtime>
        <mule.maven.plugin.version>4.1.1</mule.maven.plugin.version>
        <exchange.mule.maven.plugin>0.0.13</exchange.mule.maven.plugin>
        <!-- Mule Connectors and Modules -->
        <organizationId>{add your Anypoint Platform OrgId}</organizationId>
        <apikit.version>1.10.3</apikit.version>
        <http.connector.version>1.9.1</http.connector.version>
        <amq.connector.version>4.0.6</amq.connector.version>
        <sfdc.connector.version>10.19.4</sfdc.connector.version>
        <mule.secure.config.version>1.2.7</mule.secure.config.version>
        <os.connector.version>1.2.2</os.connector.version>
        <munit.version>3.1.0</munit.version>
        <type>custom</type>
        <!-- CloudHub Deployment Properties-->
        <mule.cloudhub.monitoring.enabled>true</mule.cloudhub.monitoring.enabled>
    </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>
                    <cloudHubDeployment>
                        <uri>https://anypoint.mulesoft.com</uri>
                        <muleVersion>${mule.app.runtime}</muleVersion>
                        <username>${mule.cloudhub.username}</username>
                        <password>${mule.cloudhub.password}</password>
                        <applicationName>${mule.cloudhub.app.name}</applicationName>
                        <environment>${mule.env}</environment>
                        <region>${mule.region}</region>
                        <workerType>${mule.workerType}</workerType>
                        <workers>${mule.workers}</workers>
                        <objectStoreV2>true</objectStoreV2>
                        <properties>
                            <mule.env>${mule.env}</mule.env>
                            <mule.encryptionKey>${mule.encryptionKey}</mule.encryptionKey>
                            <mule.cloudhub.https.port>${mule.cloudhub.https.port}</mule.cloudhub.https.port>
                            <anypoint.platform.client_id>${mule.cloudhub.env.client.id}</anypoint.platform.client_id>
                            <anypoint.platform.client_secret>${mule.cloudhub.env.client.secret}</anypoint.platform.client_secret>
                            <mule.monitoringEnabled>${mule.cloudhub.monitoring.enabled}</mule.monitoringEnabled>
                            <anypoint.platform.config.analytics.agent.enabled>${mule.cloudhub.monitoring.enabled}</anypoint.platform.config.analytics.agent.enabled>
                        </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>
                    <runtimeVersion>${mule.app.runtime}</runtimeVersion>
                    <systemPropertyVariables>
                        <mule.env>munit</mule.env>
                    </systemPropertyVariables>
                    <coverage>
                        <runCoverage>true</runCoverage>
                        <failBuild>true</failBuild>
                        <requiredApplicationCoverage>${munit.testcoverage.app}</requiredApplicationCoverage>
                        <requiredResourceCoverage>${munit.testcoverage.resource}</requiredResourceCoverage>
                        <requiredFlowCoverage>${munit.testcoverage.flow}</requiredFlowCoverage>
                        <formats>
                            <format>console</format>
                            <format>html</format>
                            <format>json</format>
                            <format>sonar</format>
                        </formats>
                    </coverage>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.mule.tools.maven</groupId>
                <artifactId>exchange-mule-maven-plugin</artifactId>
                <version>${exchange.mule.maven.plugin}</version>
                <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>
        </plugins>
    </build>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.mulesoft.munit</groupId>
                <artifactId>munit-runner</artifactId>
                <version>${munit.version}</version>
                <classifier>mule-plugin</classifier>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>com.mulesoft.munit</groupId>
                <artifactId>munit-tools</artifactId>
                <version>${munit.version}</version>
                <classifier>mule-plugin</classifier>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>com.mulesoft.modules</groupId>
                <artifactId>mule-secure-configuration-property-module</artifactId>
                <version>${mule.secure.config.version}</version>
                <classifier>mule-plugin</classifier>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <repositories>
        <!--<repository>
                        <id>mulesoft-artifacts</id>
                        <url>https://pkgs.dev.azure.com/effinium/{azure-org-id}/_packaging/mulesoft-artifacts/maven/v1</url>
                        <releases>
                                <enabled>true</enabled>
                        </releases>
                        <snapshots>
                                <enabled>true</enabled>
                        </snapshots>
                </repository> -->
        <repository>
            <id>Exchange3</id>
            <name>Anypoint Exchange</name>
            <url>https://maven.anypoint.mulesoft.com/api/v3/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>
        <!--<repository>
                        <id>mulesoft-ee</id>
                        <name>MuleSoft Enterprise Repository</name>
                        <url>https://repository.mulesoft.org/nexus-ee/content/repositories/releases-ee/</url>
                        <layout>default</layout>
                        <releases>
                                <enabled>true</enabled>
                        </releases>
                        <snapshots>
                                <enabled>true</enabled>
                        </snapshots>
                </repository> -->
    </repositories>
    <distributionManagement>
        <!--<repository>
                        <id>mulesoft-artifacts</id>
                        <url>https://pkgs.dev.azure.com/effinium/{azure-org-id}/_packaging/mulesoft-artifacts/maven/v1</url>
                        <releases>
                                <enabled>true</enabled>
                        </releases>
                        <snapshots>
                                <enabled>true</enabled>
                        </snapshots>
                </repository> -->
        <repository>
            <id>Exchange3</id>
            <name>Anypoint Platform Exchange Repository</name>
            <url>https://maven.anypoint.mulesoft.com/api/v3/organizations/${organizationId}/maven</url>
            <layout>default</layout>
        </repository>
    </distributionManagement>
    <pluginRepositories>
        <pluginRepository>
            <id>mule-public</id>
            <url>https://repository.mulesoft.org/nexus/content/repositories/releases</url>
        </pluginRepository>
        <pluginRepository>
            <id>mulesoft-release</id>
            <name>mulesoft release repository</name>
            <layout>default</layout>
            <url>https://repository.mulesoft.org/releases/</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </pluginRepository>
        <!--<pluginRepository>
                        <id>mulesoft-ee</id>
                        <name>MuleSoft Enterprise Repository</name>
                        <url>https://repository.mulesoft.org/nexus-ee/content/repositories/releases-ee/</url>
                        <layout>default</layout>
                        <releases>
                                <enabled>true</enabled>
                        </releases>
                        <snapshots>
                                <enabled>true</enabled>
                        </snapshots>
                </pluginRepository> -->
    </pluginRepositories>
</project>

Setting.xml Configuration

🥐 Open settings.xml file and add your credentials inside servers section.

You can find settings.xml in conf folder -> apache-maven-3.9.6/conf.

I have downloaded and placed it in my Developer folder -> /Users/effinium/Developer/Software/apache-maven-3.9.6/conf. Yours will be located in a different folder.

<server>
    <id>Exchange3</id>
    <username>username</username>
    <password>password</password>
</server>

Remember, the Id should be the same as you defined in Parent POM <distributionManagement> section.

Maven won’t support MFA authentication, so I highly recommend you use Connected App with Exchange Admin access.

Here is the code snippet for Connected App,

<server>
    <id>Repository</id>
    <username>~~~Client~~~</username>
    <password>clientID~?~clientSecret</password>
</server>

Alternatively, you can also use Access Token:

<server>
    <id>Repository</id>
    <username>~~~Token~~~</username>
    <password>{Your token}</password>
</server>

Here is a simplified settings.xml file.

<settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
    <pluginGroups>
        <pluginGroup>org.mule.tools</pluginGroup>
    </pluginGroups>
    <servers>
        <server>
            <id>Exchange3</id>
            <username>username</username>
            <password>password</password>
        </server>
    </servers>
    <!-- Required -->
    <profiles>
        <profile>
            <id>mulesoft-repositories</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <repositories>
                <repository>
                    <id>mulesoft-public</id>
                    <name>MuleSoft Public Repository</name>
                    <url>https://repository.mulesoft.org/nexus/content/repositories/public</url>
                    <layout>default</layout>
                </repository>
            </repositories>
            <pluginRepositories>
                <pluginRepository>
                    <id>mulesoft-public</id>
                    <url>https://repository.mulesoft.org/nexus/content/repositories/public</url>
                </pluginRepository>
            </pluginRepositories>
        </profile>
    </profiles>
</settings>

I have not added the Mule Nexus repo because I have no enterprise license.

🥐 Once you updated settings.xml file, copy the file to .m2 folder.

The directory is ~/.m2 on macOS or Linux and <default-drive>\Users\YOUR_USER_NAME\.m2 on Windows.

Deploy Parent POM to Exchange

Now, let’s deploy the Parent POM to Anypoint Exchange.

🥐 Navigate to the directory containing your parent pom.xml file.

🥐 Run mvn clean install, this will install parent pom on your local machine.

parent-pom-in-mule

🥐 Create a Hello World project and check it’s pom.xml.

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.mycompany</groupId>
    <artifactId>hello-world</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>mule-application</packaging>
    <name>hello-world</name>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <app.runtime>4.5.1</app.runtime>
        <mule.maven.plugin.version>4.0.0</mule.maven.plugin.version>
    </properties>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-clean-plugin</artifactId>
                <version>3.2.0</version>
            </plugin>
            <plugin>
                <groupId>org.mule.tools.maven</groupId>
                <artifactId>mule-maven-plugin</artifactId>
                <version>${mule.maven.plugin.version}</version>
                <extensions>true</extensions>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>org.mule.connectors</groupId>
            <artifactId>mule-http-connector</artifactId>
            <version>1.8.0</version>
            <classifier>mule-plugin</classifier>
        </dependency>
        <dependency>
            <groupId>org.mule.connectors</groupId>
            <artifactId>mule-sockets-connector</artifactId>
            <version>1.2.3</version>
            <classifier>mule-plugin</classifier>
        </dependency>
    </dependencies>
    <repositories>
        <repository>
            <id>anypoint-exchange-v3</id>
            <name>Anypoint Exchange</name>
            <url>https://maven.anypoint.mulesoft.com/api/v3/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 Releases Repository</name>
            <layout>default</layout>
            <url>https://repository.mulesoft.org/releases/</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>
</project>

Now, identify which sections we can remove because those we were already added in Parent POM.

Expect root properties and dependencies; we can remove everything.

Here is a simplified pom.xml file after refactoring.

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.effinium</groupId>
    <artifactId>hello-world</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>mule-application</packaging>
    <name>hello-world</name>
        <parent>
        <groupId>2c3f9553-58ad-4ce1-8f4b-35fdbe871782</groupId>
        <artifactId>parent-pom</artifactId>
        <version>1.0.0</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.mule.connectors</groupId>
            <artifactId>mule-http-connector</artifactId>
            <version>${http.connector.version}</version>
            <classifier>mule-plugin</classifier>
        </dependency>
    </dependencies>
</project>

Take a look at the MuleSoft project.

implement-parent-pom-in-mule

Voilà, we have added only HTTP Connector, but how was the MUnits and Secure Properties module added to the project?

Do you remember that we have added three dependencies in the <dependenciesManagement> section? That means, by default, we’re adding these dependencies in all the Mule projects.

Later, if you want to add a Salesforce connector to your project, add Salesforce dependency and update the connector version.

The version tag name must match the version tag name defined in the Parent POM properties file.

via GIPHY

Question – Nag, why can’t we add all dependencies in Parent POM rather than in Project’s POM?

Let’s assume we have added HTTP Connector dependency in Parent POM. Now, if we add a Parent POM reference in the Project’s POM, the HTTP Connector will also added to the project.

However, I’m developing a system API that doesn’t need an HTTP Connector because my requirement is subscribing to platform events and inserting them into the database.

Does adding a connector or module that is not usable in the Project make sense? NO.

🥐 Now run mvn clean deploy -DmuleDeploy to publish Parent POM to Anypoint Exchange.

publish-assets-to-exchange

🥐 Open Anypoint Exchange and search for Parent POM.

parent-pom-in-exchange

Note: I have updated the name and icon to protect my content from copycats smiles :).

Conclusion

Implementing a parent POM (Project Object Model) in Mule projects offers numerous benefits, streamlining development efforts, ensuring consistency, and promoting best practices across the organization.

By centralizing standard configurations, dependencies, and plugin configurations, developers can avoid redundant settings and maintain a cohesive structure throughout their projects.

In this guide, we have covered a step-by-step process to implement Parent POM in Mule and published it to Anypoint Exchange.

We encourage you to comment with any queries or suggestions regarding this guide. Your feedback is invaluable in refining and improving the process for our readers.

For more MuleSoft guides, news and tutorials, visit our dedicated MuleSoft DevGuides portal.

Parent POM (Project Object Model) plays a crucial role in standardizing project configurations and promoting best practices, thereby enhancing the efficiency and maintainability of Mule applications developed using Maven.

In this guide, I’ll walk you through implementing Parent POM in Mule 4 and publishing it to Anypoint Exchange.

Note: I’ll be covering only Parent POM, not BOM. Let me know if you need to learn about BOM.

What is Parent POM?

A Parent POM (Project Object Model) in Mule 4 is like a master instruction manual for building Mule applications. It contains all the standard settings, dependencies, and configurations needed for multiple Mule projects within an organization.

parent-pom-in-mule

Let’s understand with a small example.

Imagine you’re baking different types of cakes, but all cakes need flour, sugar, and eggs. The parent POM is like a recipe book with everyday ingredients and instructions.

Each specific cake recipe (or Mule project) can then build upon this foundation, adding its unique flavour (custom configurations) while still relying on the essential ingredients and instructions the parent POM provides.

So, instead of writing the exact instructions for each cake recipe separately, you have a single recipe book (the parent POM) that ensures consistency, simplifies maintenance, and helps everyone in the kitchen (development team) follow the same baking rules.

To make it easier to follow, we’ve laid out a trail of croissants to guide your way. Whenever you see a 🥐 it means there’s something for you to do.

Prerequisites

Before you begin, ensure you have the following:

Problem Statement

Let’s start by understanding the problem statement and how to leverage Parent POM to solve the problem.

As a development team working on multiple Mule applications within an organization, we encounter challenges in maintaining consistency across project configurations, managing dependencies, and ensuring adherence to best practices.

Without a standardized approach, we face issues with version mismatches, redundant configurations, and difficulties in collaboration and maintenance.

Solution

Implementing a parent POM in Mule 4 can address these challenges effectively. The parent POM is a centralized configuration file that defines standard settings, dependencies, and plugins for all Mule projects within the organization.

Implementing Parent POM in Mule 4

Analysis

🥐 First, identify your integrations’ standard configurations, dependencies, and plugins list.

🥐 Go to MuleSoft release notes and note down the latest connectors versions you will use in your integration projects.

For instance, my integrations will use HTTP Connector, APIKit, Secure Property Placeholder, Salesforce, Object Store, and Anypoint MQ.

HTTP Connector -> 1.9.1
Object Store Connector -> 1.2.2
Salesforce Connector -> 10.19.4
Anypoint MQ Connector -> 4.0.6
Secure Config Module -> 1.2.7
APIKit Module -> 1.10.3

🥐 Open any project’s POM file, and you’ll find the sections below. As these are common across all projects, we can move these configurations, plugins and dependencies to Parent POM.

  • <properties>
  • <build>
  • <dependencies>
  • <repositories>
  • <pluginRepositories>

Parent POM Configuration

🥐 Open any folder and create a file called pom.xml.

🥐 Copy & paste the content below content in your pom.xml.

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    

</project>

Update Root Values

Let’s add the name, artifactId, groupId and other values.

<modelVersion>4.0.0</modelVersion>
<groupId>{add your Anypoint Platform OrgId}</groupId>
<artifactId>parent-pom</artifactId>
<packaging>pom</packaging>
<version>1.0.0</version>
<name>parent-pom</name>

groupId must be your Anypoint Platform Organization ID if you’re deploying Assets to Anypoint Exchange.

If you deploy and manage your Assets in other Artifacts, such as Azure, you can update groupId to anything you wish.

I go with com.<company>.parentpom. Please don’t add your complete company name; make it short. For instance, com.acme.parentpom.

Properties

🥐 Add all the required properties, including connector and module versions.

This is where you can add all the connectors and module versions you intend to use in your integration projects.

Below are the generic properties for all Mule projects, so let’s add them first.

<properties>
        <!--- Generic Properties -->
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <app.runtime>4.5.1</app.runtime>
    <mule.maven.plugin.version>4.1.1</mule.maven.plugin.version>
    <exchange.mule.maven.plugin>0.0.13</exchange.mule.maven.plugin>
</properties>

Make sure to check Java compatibility for the Mule Maven Plugin. Mule Maven 4.1.1 will support Java 8, 11, and 17. Mule Maven 3.8.2will support Java 8.

I use Java 11 with the Maven 3.9.x version, so Mule Maven 4.1.1 will work for me. If you’re using Java 8 and Maven 3.6.3 to 3.8.6, please use Mule Maven 3.8.7.

Refer to Mule Maven release notes for more information.

🥐 Next, add the required Connectors, Modules and Custom Plugin versions.

<properties>
    <!-- Mule Connectors and Modules -->
    <organizationId>{add your Anypoint Platform OrgId}</organizationId>
    <apikit.version>1.10.3</apikit.version>
    <http.connector.version>1.9.1</http.connector.version>
    <amq.connector.version>4.0.6</amq.connector.version>
    <sfdc.connector.version>10.19.4</sfdc.connector.version>
    <mule.secure.config.version>1.2.7</mule.secure.config.version>
    <os.connector.version>1.2.2</os.connector.version>
    <!-- Specifcy Asset Type-->
    <type>custom</type>
    <!-- CloudHub Deployment Properties-->
    <mule.cloudhub.monitoring.enabled>true</mule.cloudhub.monitoring.enabled>
</properties>

Make sure to add type as custom – <type>custom</type>

Build

🥐 In <build> section, define plugin versions and configurations applied globally to all child projects.

It allows you to centralize plugin configurations in a parent POM so that child projects can inherit and use them without explicitly specifying the plugin versions and configurations again.

Add Mule-related Maven plugins, Generic Maven plugins, CloudHub or other deployment target configurations here and Mule extension-related plugins.

These plugins and configurations are generic for all Mule projects, so it is better to add them in pluginManagement section.

There are two plugin configurations:

  1. mule-maven-plugin (required)
  2. munit-maven-plugin (required)
  3. exchange-mule-maven-plugin is required only for Exchange deployment.
<build>
    <pluginManagement>
        <plugins>
            <!-- Mule Maven Plugin and CloudHub Deployment Configuration-->
            <plugin>
                <groupId>org.mule.tools.maven</groupId>
                <artifactId>mule-maven-plugin</artifactId>
                <version>${mule.maven.plugin.version}</version>
                <extensions>true</extensions>
                <configuration>
                    <cloudHubDeployment>
                        <uri>https://anypoint.mulesoft.com</uri>
                        <muleVersion>${mule.app.runtime}</muleVersion>
                        <username>${mule.cloudhub.username}</username>
                        <password>${mule.cloudhub.password}</password>
                        <applicationName>${mule.cloudhub.app.name}</applicationName>
                        <environment>${mule.env}</environment>
                        <region>${mule.region}</region>
                        <workerType>${mule.workerType}</workerType>
                        <workers>${mule.workers}</workers>
                        <objectStoreV2>true</objectStoreV2>
                        <properties>
                            <mule.env>${mule.env}</mule.env>
                            <mule.encryptionKey>${mule.encryptionKey}</mule.encryptionKey>
                            <mule.cloudhub.https.port>${mule.cloudhub.https.port}</mule.cloudhub.https.port>
                            <anypoint.platform.client_id>${mule.cloudhub.env.client.id}</anypoint.platform.client_id>
                            <anypoint.platform.client_secret>${mule.cloudhub.env.client.secret}</anypoint.platform.client_secret>
                            <mule.monitoringEnabled>${mule.cloudhub.monitoring.enabled}</mule.monitoringEnabled>
                            <anypoint.platform.config.analytics.agent.enabled>${mule.cloudhub.monitoring.enabled}</anypoint.platform.config.analytics.agent.enabled>
                        </properties>
                    </cloudHubDeployment>
                    <classifier>mule-application</classifier>
                </configuration>
            </plugin>
            <!-- Mule MUnit 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>
                    <runtimeVersion>${mule.app.runtime}</runtimeVersion>
                    <systemPropertyVariables>
                        <mule.env>munit</mule.env>
                    </systemPropertyVariables>
                    <coverage>
                        <runCoverage>true</runCoverage>
                        <failBuild>true</failBuild>
                        <requiredApplicationCoverage>${munit.testcoverage.app}</requiredApplicationCoverage>
                        <requiredResourceCoverage>${munit.testcoverage.resource}</requiredResourceCoverage>
                        <requiredFlowCoverage>${munit.testcoverage.flow}</requiredFlowCoverage>
                        <formats>
                            <format>console</format>
                            <format>html</format>
                            <format>json</format>
                            <format>sonar</format>
                        </formats>
                    </coverage>
                </configuration>
            </plugin>
            <!-- It's required only for Exchange Deployment-->
            <plugin>
                <groupId>org.mule.tools.maven</groupId>
                <artifactId>exchange-mule-maven-plugin</artifactId>
                <version>${exchange.mule.maven.plugin}</version>
                <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>
        </plugins>
    </pluginManagement>
</build>

You must pass the CloudHub Deployment properties in Runtime through the CI/CD pipeline.

Distribution Management

🥐 In distributionManagement section, specify where the built artefacts should be deployed. Typically, it’s used in the parent POM file to define the deployment repositories, and child projects inherit these settings.

In our case, we will deploy artefacts to Anypoint Exchnage, so add Exchnage repository details.

<distributionManagement>
    <repository>
        <id>Exchange3</id>
        <name>Anypoint Platform Exchange Repository</name>
        <url>https://maven.anypoint.mulesoft.com/api/v3/organizations/c09b2cb2-1258-47d1-a4d1-41a9f7698f34/maven</url>
        <layout>default</layout>
    </repository>
</distributionManagement>

Note down the Id (Exchange3) because you should use the same ID in your settings.xml, or else, you’ll end up with MojoFailureException

The above URL is different for the EU and Government cloud. For more information, visit MuleSoft documentation.

Dependency Management

🥐 In dependencyManagement section, add common dependencies’ versions and configurations which are generic to all Mule projects.

It allows you to specify the versions of dependencies used in your project without including them in your dependency list.

Can you guess the common dependencies?

  • Munit
  • Secure Properties Module

If you have any custom plugins, such as JSON Logger, which is required for all Mule projects, you can include them as well.

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>com.mulesoft.munit</groupId>
            <artifactId>munit-runner</artifactId>
            <version>${munit.version}</version>
            <classifier>mule-plugin</classifier>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.mulesoft.munit</groupId>
            <artifactId>munit-tools</artifactId>
            <version>${munit.version}</version>
            <classifier>mule-plugin</classifier>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>com.mulesoft.modules</groupId>
            <artifactId>mule-secure-configuration-property-module</artifactId>
            <version>${mule.secure.config.version}</version>
            <classifier>mule-plugin</classifier>
        </dependency>
    </dependencies>
</dependencyManagement>

Don’t add project-specific dependencies because it’s a centralized Parent POM; whatever you define here will be added to your Project. For instance, if you add Salesforce dependencies, they will be added to all your Projects (Exp, Process and Sys).

Repositories

Repositories are used to specify locations from where Maven can retrieve project dependencies. These dependencies typically include libraries and frameworks your project relies on for compilation, testing, and execution.

Maven searches these repositories to download JAR files and other artefacts needed for the build process.

Examples of regular repositories include Maven Central Repository and other public or private repositories hosting Java libraries and dependencies.

🥐 In repositories section, add repos such as Exchange v3, Mule EE, etc.,

<repositories>
    <!--<repository>
                        <id>mulesoft-artifacts</id>
                        <url>https://pkgs.dev.azure.com/effinium/{azure-org-id}/_packaging/mulesoft-artifacts/maven/v1</url>
                        <releases>
                                <enabled>true</enabled>
                        </releases>
                        <snapshots>
                                <enabled>true</enabled>
                        </snapshots>
                </repository> -->
    <repository>
        <id>Exchange3</id>
        <name>Anypoint Exchange</name>
        <url>https://maven.anypoint.mulesoft.com/api/v3/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>
    <!--<repository>
                        <id>mulesoft-ee</id>
                        <name>MuleSoft Enterprise Repository</name>
                        <url>https://repository.mulesoft.org/nexus-ee/content/repositories/releases-ee/</url>
                        <layout>default</layout>
                        <releases>
                                <enabled>true</enabled>
                        </releases>
                        <snapshots>
                                <enabled>true</enabled>
                        </snapshots>
                </repository> -->
</repositories>

I have also included the Azure Artifect repository for your reference. For Exchange deployment, you can ignore this repo.

If you don’t have a licence for enterprise, please remove the Nexus repo mulesoft-ee reference because it requires a username and password.

Plugin Repositories

Plugin repositories are explicitly used to specify locations from where Maven can retrieve plugins necessary for building or managing the project.

These plugins extend Maven’s functionality and are often used for tasks such as compiling code, packaging applications, running tests, and deploying artefacts.

Maven searches these repositories to download plugin artefacts required for executing build goals defined in the project’s lifecycle.

The main difference between Repositories and Plugin Repositories is regular repositories provide dependencies needed by your project. In contrast, plugin repositories provide plugins needed by Maven to perform various build tasks on your project.

🥐 In pluginRepositories section, add plugin repos such as Mule Nexus, Mule Public, etc.

    <pluginRepositories>
        <pluginRepository>
            <id>mule-public</id>
            <url>https://repository.mulesoft.org/nexus/content/repositories/releases</url>
        </pluginRepository>
        <pluginRepository>
            <id>mulesoft-release</id>
            <name>mulesoft release repository</name>
            <layout>default</layout>
            <url>https://repository.mulesoft.org/releases/</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </pluginRepository>
        <!--<pluginRepository>
                        <id>mulesoft-ee</id>
                        <name>MuleSoft Enterprise Repository</name>
                        <url>https://repository.mulesoft.org/nexus-ee/content/repositories/releases-ee/</url>
                        <layout>default</layout>
                        <releases>
                                <enabled>true</enabled>
                        </releases>
                        <snapshots>
                                <enabled>true</enabled>
                        </snapshots>
                </pluginRepository> -->
    </pluginRepositories>

If you don’t have a licence for enterprise, please remove the Nexus repo mulesoft-ee reference because it requires a username and password.

Complete Parent POM

Here is our complete Parent POM file.

<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>{add your Anypoint Platform OrgId}</groupId>
    <artifactId>parent-pom</artifactId>
    <packaging>pom</packaging>
    <version>1.0.0</version>
    <name>parent-pom</name>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <app.runtime>4.5.1</app.runtime>
        <mule.maven.plugin.version>4.1.1</mule.maven.plugin.version>
        <exchange.mule.maven.plugin>0.0.13</exchange.mule.maven.plugin>
        <!-- Mule Connectors and Modules -->
        <organizationId>{add your Anypoint Platform OrgId}</organizationId>
        <apikit.version>1.10.3</apikit.version>
        <http.connector.version>1.9.1</http.connector.version>
        <amq.connector.version>4.0.6</amq.connector.version>
        <sfdc.connector.version>10.19.4</sfdc.connector.version>
        <mule.secure.config.version>1.2.7</mule.secure.config.version>
        <os.connector.version>1.2.2</os.connector.version>
        <munit.version>3.1.0</munit.version>
        <type>custom</type>
        <!-- CloudHub Deployment Properties-->
        <mule.cloudhub.monitoring.enabled>true</mule.cloudhub.monitoring.enabled>
    </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>
                    <cloudHubDeployment>
                        <uri>https://anypoint.mulesoft.com</uri>
                        <muleVersion>${mule.app.runtime}</muleVersion>
                        <username>${mule.cloudhub.username}</username>
                        <password>${mule.cloudhub.password}</password>
                        <applicationName>${mule.cloudhub.app.name}</applicationName>
                        <environment>${mule.env}</environment>
                        <region>${mule.region}</region>
                        <workerType>${mule.workerType}</workerType>
                        <workers>${mule.workers}</workers>
                        <objectStoreV2>true</objectStoreV2>
                        <properties>
                            <mule.env>${mule.env}</mule.env>
                            <mule.encryptionKey>${mule.encryptionKey}</mule.encryptionKey>
                            <mule.cloudhub.https.port>${mule.cloudhub.https.port}</mule.cloudhub.https.port>
                            <anypoint.platform.client_id>${mule.cloudhub.env.client.id}</anypoint.platform.client_id>
                            <anypoint.platform.client_secret>${mule.cloudhub.env.client.secret}</anypoint.platform.client_secret>
                            <mule.monitoringEnabled>${mule.cloudhub.monitoring.enabled}</mule.monitoringEnabled>
                            <anypoint.platform.config.analytics.agent.enabled>${mule.cloudhub.monitoring.enabled}</anypoint.platform.config.analytics.agent.enabled>
                        </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>
                    <runtimeVersion>${mule.app.runtime}</runtimeVersion>
                    <systemPropertyVariables>
                        <mule.env>munit</mule.env>
                    </systemPropertyVariables>
                    <coverage>
                        <runCoverage>true</runCoverage>
                        <failBuild>true</failBuild>
                        <requiredApplicationCoverage>${munit.testcoverage.app}</requiredApplicationCoverage>
                        <requiredResourceCoverage>${munit.testcoverage.resource}</requiredResourceCoverage>
                        <requiredFlowCoverage>${munit.testcoverage.flow}</requiredFlowCoverage>
                        <formats>
                            <format>console</format>
                            <format>html</format>
                            <format>json</format>
                            <format>sonar</format>
                        </formats>
                    </coverage>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.mule.tools.maven</groupId>
                <artifactId>exchange-mule-maven-plugin</artifactId>
                <version>${exchange.mule.maven.plugin}</version>
                <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>
        </plugins>
    </build>
    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>com.mulesoft.munit</groupId>
                <artifactId>munit-runner</artifactId>
                <version>${munit.version}</version>
                <classifier>mule-plugin</classifier>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>com.mulesoft.munit</groupId>
                <artifactId>munit-tools</artifactId>
                <version>${munit.version}</version>
                <classifier>mule-plugin</classifier>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>com.mulesoft.modules</groupId>
                <artifactId>mule-secure-configuration-property-module</artifactId>
                <version>${mule.secure.config.version}</version>
                <classifier>mule-plugin</classifier>
            </dependency>
        </dependencies>
    </dependencyManagement>
    <repositories>
        <!--<repository>
                        <id>mulesoft-artifacts</id>
                        <url>https://pkgs.dev.azure.com/effinium/{azure-org-id}/_packaging/mulesoft-artifacts/maven/v1</url>
                        <releases>
                                <enabled>true</enabled>
                        </releases>
                        <snapshots>
                                <enabled>true</enabled>
                        </snapshots>
                </repository> -->
        <repository>
            <id>Exchange3</id>
            <name>Anypoint Exchange</name>
            <url>https://maven.anypoint.mulesoft.com/api/v3/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>
        <!--<repository>
                        <id>mulesoft-ee</id>
                        <name>MuleSoft Enterprise Repository</name>
                        <url>https://repository.mulesoft.org/nexus-ee/content/repositories/releases-ee/</url>
                        <layout>default</layout>
                        <releases>
                                <enabled>true</enabled>
                        </releases>
                        <snapshots>
                                <enabled>true</enabled>
                        </snapshots>
                </repository> -->
    </repositories>
    <distributionManagement>
        <!--<repository>
                        <id>mulesoft-artifacts</id>
                        <url>https://pkgs.dev.azure.com/effinium/{azure-org-id}/_packaging/mulesoft-artifacts/maven/v1</url>
                        <releases>
                                <enabled>true</enabled>
                        </releases>
                        <snapshots>
                                <enabled>true</enabled>
                        </snapshots>
                </repository> -->
        <repository>
            <id>Exchange3</id>
            <name>Anypoint Platform Exchange Repository</name>
            <url>https://maven.anypoint.mulesoft.com/api/v3/organizations/${organizationId}/maven</url>
            <layout>default</layout>
        </repository>
    </distributionManagement>
    <pluginRepositories>
        <pluginRepository>
            <id>mule-public</id>
            <url>https://repository.mulesoft.org/nexus/content/repositories/releases</url>
        </pluginRepository>
        <pluginRepository>
            <id>mulesoft-release</id>
            <name>mulesoft release repository</name>
            <layout>default</layout>
            <url>https://repository.mulesoft.org/releases/</url>
            <snapshots>
                <enabled>true</enabled>
            </snapshots>
        </pluginRepository>
        <!--<pluginRepository>
                        <id>mulesoft-ee</id>
                        <name>MuleSoft Enterprise Repository</name>
                        <url>https://repository.mulesoft.org/nexus-ee/content/repositories/releases-ee/</url>
                        <layout>default</layout>
                        <releases>
                                <enabled>true</enabled>
                        </releases>
                        <snapshots>
                                <enabled>true</enabled>
                        </snapshots>
                </pluginRepository> -->
    </pluginRepositories>
</project>

Setting.xml Configuration

🥐 Open settings.xml file and add your credentials inside servers section.

You can find settings.xml in conf folder -> apache-maven-3.9.6/conf.

I have downloaded and placed it in my Developer folder -> /Users/effinium/Developer/Software/apache-maven-3.9.6/conf. Yours will be located in a different folder.

<server>
    <id>Exchange3</id>
    <username>username</username>
    <password>password</password>
</server>

Remember, the Id should be the same as you defined in Parent POM <distributionManagement> section.

Maven won’t support MFA authentication, so I highly recommend you use Connected App with Exchange Admin access.

Here is the code snippet for Connected App,

<server>
    <id>Repository</id>
    <username>~~~Client~~~</username>
    <password>clientID~?~clientSecret</password>
</server>

Alternatively, you can also use Access Token:

<server>
    <id>Repository</id>
    <username>~~~Token~~~</username>
    <password>{Your token}</password>
</server>

Here is a simplified settings.xml file.

<settings xmlns="http://maven.apache.org/SETTINGS/1.1.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
    <pluginGroups>
        <pluginGroup>org.mule.tools</pluginGroup>
    </pluginGroups>
    <servers>
        <server>
            <id>Exchange3</id>
            <username>username</username>
            <password>password</password>
        </server>
    </servers>
    <!-- Required -->
    <profiles>
        <profile>
            <id>mulesoft-repositories</id>
            <activation>
                <activeByDefault>true</activeByDefault>
            </activation>
            <repositories>
                <repository>
                    <id>mulesoft-public</id>
                    <name>MuleSoft Public Repository</name>
                    <url>https://repository.mulesoft.org/nexus/content/repositories/public</url>
                    <layout>default</layout>
                </repository>
            </repositories>
            <pluginRepositories>
                <pluginRepository>
                    <id>mulesoft-public</id>
                    <url>https://repository.mulesoft.org/nexus/content/repositories/public</url>
                </pluginRepository>
            </pluginRepositories>
        </profile>
    </profiles>
</settings>

I have not added the Mule Nexus repo because I have no enterprise license.

🥐 Once you updated settings.xml file, copy the file to .m2 folder.

The directory is ~/.m2 on macOS or Linux and <default-drive>\Users\YOUR_USER_NAME\.m2 on Windows.

Deploy Parent POM to Exchange

Now, let’s deploy the Parent POM to Anypoint Exchange.

🥐 Navigate to the directory containing your parent pom.xml file.

🥐 Run mvn clean install, this will install parent pom on your local machine.

parent-pom-in-mule

🥐 Create a Hello World project and check it’s pom.xml.

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.mycompany</groupId>
    <artifactId>hello-world</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>mule-application</packaging>
    <name>hello-world</name>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <app.runtime>4.5.1</app.runtime>
        <mule.maven.plugin.version>4.0.0</mule.maven.plugin.version>
    </properties>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-clean-plugin</artifactId>
                <version>3.2.0</version>
            </plugin>
            <plugin>
                <groupId>org.mule.tools.maven</groupId>
                <artifactId>mule-maven-plugin</artifactId>
                <version>${mule.maven.plugin.version}</version>
                <extensions>true</extensions>
            </plugin>
        </plugins>
    </build>
    <dependencies>
        <dependency>
            <groupId>org.mule.connectors</groupId>
            <artifactId>mule-http-connector</artifactId>
            <version>1.8.0</version>
            <classifier>mule-plugin</classifier>
        </dependency>
        <dependency>
            <groupId>org.mule.connectors</groupId>
            <artifactId>mule-sockets-connector</artifactId>
            <version>1.2.3</version>
            <classifier>mule-plugin</classifier>
        </dependency>
    </dependencies>
    <repositories>
        <repository>
            <id>anypoint-exchange-v3</id>
            <name>Anypoint Exchange</name>
            <url>https://maven.anypoint.mulesoft.com/api/v3/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 Releases Repository</name>
            <layout>default</layout>
            <url>https://repository.mulesoft.org/releases/</url>
            <snapshots>
                <enabled>false</enabled>
            </snapshots>
        </pluginRepository>
    </pluginRepositories>
</project>

Now, identify which sections we can remove because those we were already added in Parent POM.

Expect root properties and dependencies; we can remove everything.

Here is a simplified pom.xml file after refactoring.

<?xml version="1.0" encoding="UTF-8"?>
<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 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>com.effinium</groupId>
    <artifactId>hello-world</artifactId>
    <version>1.0.0-SNAPSHOT</version>
    <packaging>mule-application</packaging>
    <name>hello-world</name>
        <parent>
        <groupId>2c3f9553-58ad-4ce1-8f4b-35fdbe871782</groupId>
        <artifactId>parent-pom</artifactId>
        <version>1.0.0</version>
    </parent>
    <dependencies>
        <dependency>
            <groupId>org.mule.connectors</groupId>
            <artifactId>mule-http-connector</artifactId>
            <version>${http.connector.version}</version>
            <classifier>mule-plugin</classifier>
        </dependency>
    </dependencies>
</project>

Take a look at the MuleSoft project.

implement-parent-pom-in-mule

Voilà, we have added only HTTP Connector, but how was the MUnits and Secure Properties module added to the project?

Do you remember that we have added three dependencies in the <dependenciesManagement> section? That means, by default, we’re adding these dependencies in all the Mule projects.

Later, if you want to add a Salesforce connector to your project, add Salesforce dependency and update the connector version.

The version tag name must match the version tag name defined in the Parent POM properties file.

via GIPHY

Question – Nag, why can’t we add all dependencies in Parent POM rather than in Project’s POM?

Let’s assume we have added HTTP Connector dependency in Parent POM. Now, if we add a Parent POM reference in the Project’s POM, the HTTP Connector will also added to the project.

However, I’m developing a system API that doesn’t need an HTTP Connector because my requirement is subscribing to platform events and inserting them into the database.

Does adding a connector or module that is not usable in the Project make sense? NO.

🥐 Now run mvn clean deploy -DmuleDeploy to publish Parent POM to Anypoint Exchange.

publish-assets-to-exchange

🥐 Open Anypoint Exchange and search for Parent POM.

parent-pom-in-exchange

Note: I have updated the name and icon to protect my content from copycats smiles :).

Conclusion

Implementing a parent POM (Project Object Model) in Mule projects offers numerous benefits, streamlining development efforts, ensuring consistency, and promoting best practices across the organization.

By centralizing standard configurations, dependencies, and plugin configurations, developers can avoid redundant settings and maintain a cohesive structure throughout their projects.

In this guide, we have covered a step-by-step process to implement Parent POM in Mule and published it to Anypoint Exchange.

We encourage you to comment with any queries or suggestions regarding this guide. Your feedback is invaluable in refining and improving the process for our readers.

For more MuleSoft guides, news and tutorials, visit our dedicated MuleSoft DevGuides portal.

4 COMMENTS

Subscribe
Notify of
guest
4 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
suraj
suraj
7 months ago

Good Work @Nagaraju

Sush K
Sush K
5 months ago

Can you also implement BOM file?

Sush K
Sush K
5 months ago

Where can I find the value of {azure-org-id} ? is it azure tenant? Thank you for the writing.

Joaquin
Joaquin
4 months ago

Great work!!!

Similar Guides.

The Ultimate Guide to Async Scope in Mule 4

This is an absolute beginner's guide to Async Scope...

How to Send MuleSoft Logs to Splunk: A Complete Guide

Integrating MuleSoft logs with Splunk enables seamless data management...
4
0
Would love your thoughts, please comment.x
()
x