How to define a BOM for our Mule Apps

 

In our previous post, we learnt why a BOM file is important for our Mule apps. In this post, we will see in detail how to build a BOM file for our Mule apps. Let’s dive in!


Maven Coordinates

First, create a new Mule Project in Anypoint Studio and open the pom.xml file. It should be located at the root folder of our project. As in any Mulesoft (and Maven) artifact, we need to provide coordinates for the BOM.
  • groupId - If you’re planning to store the BOM file in Exchange here you’ll have to provide the Org Id or Business Group Id where you’ll be deploying the BOM. Some customers prefer to deploy the BOM 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 BOM artifact
  • 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 - This is the most important coordinate for the BOM. We must specify the packaging as pom so that Maven consider it a BOM (or a parent pom).
<groupId>fc9e3283-a489-4e88-99aa-cceea4aa5ea1</groupId>
<artifactId>gon-bom</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>


Define custom properties for the list of versions

This is optional but it’s definitely very useful (and good practice). Instead of specifying the version of each plugin or dependency in the declaration of the plugin/dependency itself, we can create a custom property for each dependency/plugin version and then reference the version from the plugin/dependency. 

This way, it’s much easier to see the version numbers and becomes much quicker to change a version number, rather than scrolling down and looking for the specific plugin/dependency. Here’s an example of plugins and dependencies for which we are creating a custom property. There can be (there will be!) many more plugins and dependencies, remember that in the BOM we’re not packaging all of them, it’s just a list where we control the versions numbers.

<project>
<properties>
...
<!-- List of Plugins -->
<mule.maven.plugin.version>4.1.0</mule.maven.plugin.version>
<maven.resources.version>3.2.0</maven.resources.version>
<maven.clean.version>3.2.0</maven.clean.version>
<!-- List of Connectors/Dependencies -->
<http.connector.version>1.9.1</http.connector.version>
<sockets.connector.version>1.2.4</sockets.connector.version>
<db.connector.version>1.14.6</db.connector.version>
<apikit.version>1.9.2</apikit.version>
<secure.properties.version>1.2.7</secure.properties.version>
<mysql.connector.version>8.0.30</mysql.connector.version>
<salesforce.connector.version>10.20.0</salesforce.connector.version>
...
</properties>
</project>


List of Plugins

Next, we’ll declare the list of plugins for which this BOM will manage the versions. For that, we need to use the pluginManagement element and put it within the build section. This is what it would look like for the three plugins of our example.

<project>
...
<build>
<pluginManagement>
<plugins>
...
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>${maven.resources.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>${maven.clean.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>
<classifier>mule-plugin</classifier>
</configuration>
</plugin>
...
</plugins>
</pluginManagement>
</build>
...
</project>

Notice that we’re not providing directly the version number for each connector. The value is picked up from the corresponding maven property defined in the previous step. This way we won’t have to modify this section anymore, we’ll change the version numbers from the properties.


List of Dependencies

And lastly, we provide the list of dependencies. These dependencies need to be declared within the dependencyManagement element. Rembember, from the previous post, that this is how Maven knows that the dependencies in this section won’t be included in the jar package. The most common dependency that we use in Mule are the connectors, so in this section is where we’ll include the list of all connectors that our organization uses.

Here’s an example with some connectors:

<project>
...
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.mule.connectors</groupId>
<artifactId>mule-http-connector</artifactId>
<version>${http.connector.version}</version>
<classifier>mule-plugin</classifier>
</dependency>
<dependency>
<groupId>org.mule.connectors</groupId>
<artifactId>mule-sockets-connector</artifactId>
<version>${sockets.connector.version}</version>
<classifier>mule-plugin</classifier>
</dependency>
<dependency>
<groupId>org.mule.modules</groupId>
<artifactId>mule-apikit-module</artifactId>
<version>${apikit.version}</version>
<classifier>mule-plugin</classifier>
</dependency>
<dependency>
<groupId>com.mulesoft.modules</groupId>
<artifactId>mule-secure-configuration-property-module</artifactId>
<version>${secure.properties.version}</version>
<classifier>mule-plugin</classifier>
</dependency>

<dependency>
<groupId>org.mule.connectors</groupId>
<artifactId>mule-db-connector</artifactId>
<version>${db.connector.version}</version>
<classifier>mule-plugin</classifier>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.connector.version}</version>
</dependency>
<dependency>
<groupId>com.mulesoft.connectors</groupId>
<artifactId>mule-salesforce-connector</artifactId>
<version>${salesforce.connector.version}</version>
<classifier>mule-plugin</classifier>
</dependency>
</dependencies>
</dependencyManagement>
...
</project>

Again, note that in here the versions numbers reference the custom property we define in the initial steps.


With that, our final BOM file will look like this:

<?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>fc9e3283-a489-4e88-99aa-cceea4aa5ea1</groupId>
<artifactId>gon-bom</artifactId>
<version>1.0.0</version>
<packaging>pom</packaging>

<name>gon-bom</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>
<!-- List of Plugins -->
<mule.maven.plugin.version>4.1.0</mule.maven.plugin.version>
<maven.resources.version>3.2.0</maven.resources.version>
<maven.clean.version>3.2.0</maven.clean.version>
<!-- List of Connectors/Dependencies -->
<http.connector.version>1.9.1</http.connector.version>
<sockets.connector.version>1.2.4</sockets.connector.version>
<db.connector.version>1.14.6</db.connector.version>
<apikit.version>1.9.2</apikit.version>
<secure.properties.version>1.2.7</secure.properties.version>
<mysql.connector.version>8.0.30</mysql.connector.version>
<salesforce.connector.version>10.20.0</salesforce.connector.version>
</properties>

<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-resources-plugin</artifactId>
<version>${maven.resources.version}</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>${maven.clean.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>
<classifier>mule-plugin</classifier>
</configuration>
</plugin>

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

<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.mule.connectors</groupId>
<artifactId>mule-http-connector</artifactId>
<version>${http.connector.version}</version>
<classifier>mule-plugin</classifier>
</dependency>
<dependency>
<groupId>org.mule.connectors</groupId>
<artifactId>mule-sockets-connector</artifactId>
<version>${sockets.connector.version}</version>
<classifier>mule-plugin</classifier>
</dependency>
<dependency>
<groupId>org.mule.modules</groupId>
<artifactId>mule-apikit-module</artifactId>
<version>${apikit.version}</version>
<classifier>mule-plugin</classifier>
</dependency>
<dependency>
<groupId>com.mulesoft.modules</groupId>
<artifactId>mule-secure-configuration-property-module</artifactId>
<version>${secure.properties.version}</version>
<classifier>mule-plugin</classifier>
</dependency>

<dependency>
<groupId>org.mule.connectors</groupId>
<artifactId>mule-db-connector</artifactId>
<version>${db.connector.version}</version>
<classifier>mule-plugin</classifier>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.connector.version}</version>
</dependency>
<dependency>
<groupId>com.mulesoft.connectors</groupId>
<artifactId>mule-salesforce-connector</artifactId>
<version>${salesforce.connector.version}</version>
<classifier>mule-plugin</classifier>
</dependency>
</dependencies>
</dependencyManagement>
</project>


Install the BOM

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

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

To do that, open a terminal from the folder of your bom project (in Studio, right click on the project name > Show in > System Explorer. From there run the following:

mvn clean install


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

Test the BOM

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


Reference the BOM file

At the begining of the pom file, we need to declare the BOM with the parent element. For that, we need to specify the maven coordinates of our BOM project.
<project>
...
<parent>
<groupId>fc9e3283-a489-4e88-99aa-cceea4aa5ea1</groupId>
<artifactId>gon-bom</artifactId>
<version>1.0.0</version>
</parent>
...
</project>


Add your plugins and dependencies and remove the version

Next, in our pom we need to specify the plugins and dependencies that we’ll use for our Mule app. For that, we will declare them as we always do, with the maven coordinates of each plugin/dependency. The beauty of using the BOM, is that now we don’t have to include the version tag, we can simply remove it. When Maven will build the project it will go to the BOM to pick up the version of each dependency.

So, for example, let’s say we want the following plugins and connectors for our new mule app:
  • Plugins - These two plugins are included in all Mule apps by default
    • Maven Clean plugin
    • Mule Maven Plugin
  • Connectors - If we build a REST API we will include:
    • HTTP Connector
    • Sockets Connector
    • API Kit router - to use an API spec
    • Secure Properties connector - to encrypt credentials
This is how we would declare them in the pom file when using a BOM file as a parent:

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

Notice that we are not including the version in the maven coordinates of any plugin or connector. Now, if you save the POM file you will see that, automatically, Anypoint Studio will download the dependencies with the version number of our BOM file. 

Do another test - Go to your BOM file, change the version number of one or more of these connectors. Save the BOM and re-install it with mvn clean install . Get back to your app, make any change to the POM file, just to be able to save it again, and you’ll see that Anypoint Studio will update the version of those connectors automatically.


With our last test, it should be enough to see that our BOM file is working. But, to make a proper and complete test, create a simple flow for a hello world endpoint and run the project. You’ll see that Maven compiles and builds your app with no issue and your application works. All of that without having to specify any dependency version.

The beauty of using the BOM is that, in the future, when we’ll need to update the version of any of the connectors our app uses we won’t have to modify this app or any of the apps using the BOM file. We’ll only need to make the changes to one file to change the version of our connectors in one file - the BOM file. 

Previous Post Next Post