How to define a parent POM for our Mule apps


We’ve recently learnt in a previous post, what is a parent POM and how it can help our Mule apps. Now it’s time to see it in practice. In this post, we’ll see, step by step, how to define a parent POM and how to use it from a child mule project.

These are the steps to follow:


Linking a BOM

This is an optional step but very useful in my opinion. We’ve seen recently the importance of having a Bill of Materials (BOM) for our Mule apps in this post, and we’ve also seen that parent POM and BOM are not the same. In fact, BOM and parent POM are complementary, we should use both. 

Question is, how can I use both if I can only declare one parent POM for my mule apps? How do I reference both?

One way to do it (there are other ways), is to reference the BOM as the parent POM of the parent POM. It sounds confusing but it’s simple.
In our parent POM, at the begining of the pom.xml we just need to include the coordinates of the BOM:

<parent>
<groupId>[YOUR_ANYPOINT_ORG_ID]</groupId>
<artifactId>bom</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>
</parent>

This way, all of our child mule projects will inherit all the elements defined in the parent POM. And, on the other hand, the versions of all plugins and dependencies of the child mule project will be managed by the BOM. 

Dependencies in Maven are transitive, which means that child projects will inherit from the parent POM and from the dependencies of the parent POM (in our case the BOM).
With this approach also, we don’t have to specify the versions for the dependencies in the parent POM, they will be picked up from the linked BOM.

Parent POM Coordinates

Next, we need to specify the Maven coordinates for our POM file.
  • groupId - If you’re planning to store the parent POM file in Exchange here we’ll provide the Org Id or Business Group Id of our Anypoint org. Some customers deploy the parent POM to a private repository like Nexus of JFrog. In these cases, we typically use the reverse domain name, e.g. com.company.my
  • artifactid - Provide a name for the parent POM.
  • version - we’ll start with 1.0.0 in this example but obviously this is something that we’ll be changing over time and redeploying with each new version.
  • packaging - For a parent POM, we must specify the packaging as pom so that Maven knows this is a parent pom and not a mule app.
<groupId>[YOUR_ANYPOINT_ORG_ID]</groupId>
<artifactId>parent-pom</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>


Common elements for our Mule Apps

The rest of our parent POM file will be the definition of all the elements that will be inherited by our child mule projects. In this post we’ll just use a simple example, but if you want to deep dive into everything we could include into a parent POM check out this other post. In particular, we’ll put the following to be shared with all our mule apps:

Plugins
  • Mule Maven Plugin
  • Maven Clean Plugin
Dependencies (Connectors):
  • HTTP Connector
  • Sockets Connector
  • Secure Properties module
  • APIkit router
Here’s the full pom.xml of our parent POM:

<?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>

<parent>
<groupId>fc9e3283-a489-4e88-99aa-cceea4aa5ea1</groupId>
<artifactId>gon-bom</artifactId>
<version>1.0.0</version>
</parent>

<groupId>fc9e3283-a489-4e88-99aa-cceea4aa5ea1</groupId>
<artifactId>gon-parent-pom</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>

<name>gon-parent-pom</name>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<app.runtime>4.6.1</app.runtime>
<mule.maven.plugin.version>4.1.0</mule.maven.plugin.version>
</properties>

<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.mule.tools.maven</groupId>
<artifactId>mule-maven-plugin</artifactId>
<extensions>true</extensions>
</plugin>
</plugins>
</build>

<dependencies>
<dependency>
<groupId>org.mule.modules</groupId>
<artifactId>mule-apikit-module</artifactId>
<classifier>mule-plugin</classifier>
</dependency>
<dependency>
<groupId>org.mule.connectors</groupId>
<artifactId>mule-http-connector</artifactId>
<classifier>mule-plugin</classifier>
</dependency>
<dependency>
<groupId>com.mulesoft.modules</groupId>
<artifactId>mule-secure-configuration-property-module</artifactId>
<classifier>mule-plugin</classifier>
</dependency>
<dependency>
<groupId>org.mule.connectors</groupId>
<artifactId>mule-sockets-connector</artifactId>
<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>

Notice that we haven’t included the versions numbers for plugins and dependencies. Those versions will be inherited by the BOM.

Install the parent POM

Once our parent POM definition is ready, the last step is to make it available for future projects/apps. In this post, we’ll be installing the parent POM to our local maven repository (~/.m2/repository) for simplicity. In future posts, we’ll see how to deploy it to Exchange or to a private repository, which is the best practice for an organization with a team of developers.

For that, we’ll run the maven commands with the maven installation of our system, not with the embedded maven instance in Anypoint Studio.

Open a terminal from the folder of your parent POM project (in Anypoint Studio, right click on the project name > Show in > System Explorer. From there run the following:

mvn clean install


Verify that our parent POM is now available in our local repository. Go to your [HOME_DIRECTORY]/.m2/repository and look for the maven coordinates of your parent POM. 

Test the parent POM

Time to see if it works. Create a new Mule project and open the pom.xml. This is how to use the parent POM:

Reference the parent POM

At the begining of the pom file of our test project, we need to declare the parent POM with the parent element. For that, we need to specify the maven coordinates of our recently created parent POM project.

<project>
...
<parent>
<groupId>[YOUR_ANYPOINT_ORG_ID]</groupId>
<artifactId>parent-pom</artifactId>
<version>1.0.0</version>
</parent>
...
</project>


Remove the redundant elements

You’ll notice that there are some elements that Anypoint Studio includes by default with each new Mule project that are part of our parent POM. We don’t need them anymore, as they will be automatically imported from our parent POM, so we can remove the following:
  • Properties
  • Plugins:
    • Mule Maven Plugin
    • Maven Clean Plugin
  • Dependencies (Connectors):
    • HTTP Connector
    • Sockets Connector
Removing those common dependencies our final pom for a child Mule project will be:

<?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>

<parent>
<groupId>[YOUR_ANYPOINT_ORG_ID]</groupId>
<artifactId>parent-pom</artifactId>
<version>1.0.0</version>
</parent>

<groupId>[YOUR_ANYPOINT_ORG_ID]</groupId>
<artifactId>mule-child-test</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>mule-application</packaging>

<name>mule-child-test</name>

<build>
<plugins>
</plugins>
</build>

<dependencies>
</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>

With that, right after you Save the pom.xml file, you will see that Anypoint Studio automatically downloads the dependencies in our parent POM. Double check the left panel of Studio:



Notice as well that, Anypoint Studio is picking up the versions from the BOM. That means our project is inheriting from our parent POM and BOM files. Nice!

Our final test - Create a simple flow for a hello-world app and run it, just to make sure we can build our project.


What’s Next?

Now that we know the basics of how to use parent POMs and BOMs, the next step is define both for our organization. For that, we’ll have to look carefully into the pom files of our apps and identify what elements are common across our mule projects so that we can put them into our parent POM. Think of properties, plugins, dependencies, connectors... Use this posts to give you some ideas of what we can put in our parent POM:
Previous Post Next Post