In previous posts, we’ve seen how to use the Mule Maven Plugin (MMP) to automate the deployment of our Mule apps to the different deployment targets - Standalone, Cloudhub 1.0, Cloudhub 2.0 and Runtime Fabric.
In all of those examples, we were hard-coding the values for the configuration of the Mule Maven Plugin. This is not how we would do it in a Production scenario.
Why Parametrize Mule Deployments?
But before we see how to do it, why is it important to parametrize the deployments? Here’s a list of good reasons:Environment-Specific Configuration:
- Our Mule applications normally will require different settings per environment (like database credentials, URLs, or API keys). Hardcoding these configurations into the application would require manual changes when moving between environments, which is prone to errors and inefficient.
- It helps us to create a (unique) implementation that does not need to be modified when changing the environment. This ensures that the application is more portable and easier to maintain.
Automation and Continuous Integration/Continuous Deployment (CI/CD):
- With parameterization, we can automate the deployment process. The same deployment pipeline can be used for all environments by simply passing different parameters.
- This is a key practice for CI/CD pipelines, where deployments should be repeatable, reliable, and automated without manual intervention.
Security and Best Practices:
Sensitive data such as API keys, passwords, and credentials should NEVER be hardcoded. Parameterizing these values allows us to externalize sensitive information into configuration files or secure vaults.Ease of Maintenance:
Parametrization reduces the need to maintain multiple versions of the same application for different environments. Instead, a single version of the app can be deployed with different configurations depending on the target environment.How to Parametrize the Mule Maven Plugin configuration
Let’s take an example of a Mule Maven Plugin configuration for Cloudhub 2.0 where the values are hardcoded.<plugin>
<groupId>org.mule.tools.maven</groupId>
<artifactId>mule-maven-plugin</artifactId>
<version>4.3.0</version>
<extensions>true</extensions>
<configuration>
<cloudhub2Deployment>
<uri>https://anypoint.mulesoft.com</uri>
<provider>MC</provider>
<businessGroupId>fc9e3283-a489-4e88-99aa-cceea4aa5ea1</businessGroupId>
<environment>Sandbox</environment>
<target>GON-PS</target>
<muleVersion>4.8.0</muleVersion>
<server>anypoint-exchange-v3</server>
<applicationName>my-mule-app</applicationName>
<replicas>1</replicas>
<vCores>0.1</vCores>
<properties>
<api.manager.autodiscoveryId>12345</api.manager.autodiscoveryId>
</properties>
<secureProperties>
<anypoint.platform.client_id>85956be2d60c94742e4ec6487f50578d</anypoint.platform.client_id>
<anypoint.platform.client_secret>k598u517d2d9te085969c947485287f50</anypoint.platform.client_secret>
</secureProperties>
</cloudhub2Deployment>
</configuration>
</plugin>
Reference Maven Properties
Maven properties are often defined in the<properties>
section of our pom.xml
file. We can define custom properties or override built-in Maven properties.Once defined, Maven properties can be referenced throughout the
pom.xml
or in other Maven-related configurations.We can refer to any property by using the
${propertyName}
syntax.For example, we can define a property for the version of the Mule Maven Plugin and the Mule Runtime version in the POM file and reference those values in the configuration of the plugin:
<project>
...
<properties>
...
<app.runtime>4.8.0</app.runtime>
<mule.maven.plugin.version>4.3.0</mule.maven.plugin.version>
...
</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>
<cloudhub2Deployment>
...
<muleVersion>${app.runtime}</muleVersion>
...
</cloudhub2Deployment>
</configuration>
</plugin>
</plugins>
</build>
...
</project>
Reference Elements in the POM file
We can also pick up values from other elements in the POM file, not only the ones in the<properties>
section. For example, we can use the Maven coordinates of the mule app:- The mule application name can be taken from the
artifactId
- The businessGroupId where we’ll deploy the app is something that is also defined in the
groupId
<project>
<groupId>fc9e3283-a489-4e88-99aa-cceea4aa5ea1</groupId>
<artifactId>deploy-to-ch2</artifactId>
<version>1.0.0</version>
<packaging>mule-application</packaging>
<name>deploy-to-ch2</name>
...
<properties>
...
<app.runtime>4.8.0</app.runtime>
<mule.maven.plugin.version>4.3.0</mule.maven.plugin.version>
...
</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>
<cloudhub2Deployment>
...
<businessGroupId>${project.groupId}</businessGroupId>
<muleVersion>${app.runtime}</muleVersion>
<applicationName>${project.artifactId}</applicationName>
...
</cloudhub2Deployment>
</configuration>
</plugin>
</plugins>
</build>
...
</project>
<properties>
element don’t need that, e.g. the mule runtime can be reference with the syntax ${app.runtime}, no need to use the whole path of elements like ${project.properties.app.runtime}Pass Parameters via Command Line
We can define the value of our properties using the Maven CLI with the syntax-Dproperty=value
. Property values coming from the command line will override the values defined in the POM.For example, some values that are good candidates to be set up via Command line are:
- vcores
- replicas
<project>
<groupId>fc9e3283-a489-4e88-99aa-cceea4aa5ea1</groupId>
<artifactId>deploy-to-ch2</artifactId>
<version>1.0.0</version>
<packaging>mule-application</packaging>
<name>deploy-to-ch2</name>
...
<properties>
...
<app.runtime>4.8.0</app.runtime>
<mule.maven.plugin.version>4.3.0</mule.maven.plugin.version>
...
</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>
<cloudhub2Deployment>
...
<businessGroupId>${project.groupId}</businessGroupId>
<muleVersion>${app.runtime}</muleVersion>
<applicationName>${project.artifactId}</applicationName>
<replicas>${replicas}</replicas>
<vCores>${vcores}</vCores>
...
</cloudhub2Deployment>
</configuration>
</plugin>
</plugins>
</build>
...
</project>
mvn clean deploy -DmuleDeploy -Dreplicas=1 -Dvcores=0.1
Pass Parameters via Environment Variables
Similarly, we can pass the values of properties using Environment variables. For that, we need to use the syntax ${env.property}.For example, we could define the value of environment and target using environment variables. This way we can replace the hard-coded values for replicas and vcores like this:
<project>
<groupId>fc9e3283-a489-4e88-99aa-cceea4aa5ea1</groupId>
<artifactId>deploy-to-ch2</artifactId>
<version>1.0.0</version>
<packaging>mule-application</packaging>
<name>deploy-to-ch2</name>
...
<properties>
...
<app.runtime>4.8.0</app.runtime>
<mule.maven.plugin.version>4.3.0</mule.maven.plugin.version>
...
</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>
<cloudhub2Deployment>
...
<businessGroupId>${project.groupId}</businessGroupId>
<muleVersion>${app.runtime}</muleVersion>
<applicationName>${project.artifactId}</applicationName>
<replicas>${replicas}</replicas>
<vCores>${vcores}</vCores>
<environment>${env.environment}</environment>
<target>${env.target}</target>
...
</cloudhub2Deployment>
</configuration>
</plugin>
</plugins>
</build>
...
</project>
export environment=Sandbox
export target=GON-PS
mvn clean deploy -DmuleDeploy -Dreplicas=1 -Dvcores=0.1
This way of passing parameters can be used by automation tools like Jenkins or Github actions. It’s a good way for controlling the environment to which we’d deploy. These tools allow us to define environment variables for the workflows or jobs that will be running the maven commands to deploy our mule apps.
For example, Github Actions will map all the variables and secrets to environment variables in the runner of the GitHub action.
So, for example, we could include in the properties section of a parent POM properties for the
Use a Parent POM
As we’ve seen recently in previous posts, properties can be defined in the POM file of our app but also in a parent POM. When all your applications or a group of them share some common parameters and properties, a parent POM can help us to reduce redundancy in the configuration of our deployments.So, for example, we could include in the properties section of a parent POM properties for the
uri
and provider
elements of the mule maven plugin. This way our parent POM will be: <project>
...
<groupId>[YOUR_ANYPOINT_ORG_ID]</groupId>
<artifactId>parent-pom</artifactId>
<version>1.0.0</version>
...
<properties>
<anypoint.uri>https://anypoint.mulesoft.com</anypoint.uri>
<anypoint.provider>MC</anypoint.provider>
</properties>
...
</project>
And then, in the pom file of our app we will include the parent POM and the references to those properties in the plugin configuration
<project>
...
<parent>
<groupId>[YOUR_ANYPOINT_ORG_ID]</groupId>
<artifactId>parent-pom</artifactId>
<version>1.0.0</version>
</parent>
<groupId>fc9e3283-a489-4e88-99aa-cceea4aa5ea1</groupId>
<artifactId>deploy-to-ch2</artifactId>
<version>1.0.0</version>
<packaging>mule-application</packaging>
<name>deploy-to-ch2</name>
...
<properties>
...
<app.runtime>4.8.0</app.runtime>
<mule.maven.plugin.version>4.3.0</mule.maven.plugin.version>
...
</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>
<cloudhub2Deployment>
...
<uri>${anypoint.uri}</uri>
<provider>${anypoint.provider}</provider>
<businessGroupId>${project.groupId}</businessGroupId>
<muleVersion>${app.runtime}</muleVersion>
<applicationName>${project.artifactId}</applicationName>
<replicas>${replicas}</replicas>
<vCores>${vcores}</vCores>
<environment>${env.environment}</environment>
<target>${env.target}</target>
...
</cloudhub2Deployment>
</configuration>
</plugin>
</plugins>
</build>
</project>
Use the settings.xml file
The configuration file can use the maven properties using the same syntax. Normally, these properties would be global to the user or the machine running the maven commands for deployment. Properties in the settings files are particularly useful for credentials, environment-specific configurations, and user-specific values.For example, as we saw in previous posts, when using a Connected App for the authentication of the Mule Maven Plugin, the Connected App credentials can be stored in the settings.xml. For that, in the Mule Maven Configuration we use the
<server>
element<plugin>
<groupId>org.mule.tools.maven</groupId>
<artifactId>mule-maven-plugin</artifactId>
<version>4.3.0</version>
<extensions>true</extensions>
<configuration>
<cloudhub2Deployment>
...
<uri>${anypoint.uri}</uri>
<provider>${anypoint.provider}</provider>
<businessGroupId>${project.groupId}</businessGroupId>
<muleVersion>${app.runtime}</muleVersion>
<applicationName>${project.artifactId}</applicationName>
<replicas>${replicas}</replicas>
<vCores>${vcores}</vCores>
<environment>${env.environment}</environment>
<target>${env.target}</target>
<server>anypoint-exchange-v3</server>
...
</cloudhub2Deployment>
</configuration>
</plugin>
<settings>
…
<servers>
…
<server>
<id>anypoint-exchange-v3</id>
<username>~~~Client~~~</username>
<password>91f732bf23ff4575830b0c86302b9357~?~8090d2CcE1694d03a2b33Ac78339e660</password>
</server>
…
</servers>
…
</settings>
And again, in the settings file we could define maven properties for the credentials, so that, even if the file is not accessible to developers, we don’t put any credentials value in the file. We could rewrite the settings file like this:
<settings>
…
<servers>
…
<server>
<id>anypoint-exchange-v3</id>
<username>~~~Client~~~</username>
<password>${env.clientId}~?~${env.clientSecret}</password>
</server>
…
</servers>
…
</settings>
Use Maven Profiles
Lastly, Maven Profiles can be a very interesting way of defining different sets of properties that would be used based on the environment or deployment target.For example, we could define two profiles: one for dev and one for prod, and define the same properties with different values in them. For instance, for the parameters required for API Manager we could define something like this:
<profiles>
<profile>
<id>dev</id>
<properties>
<api.manager.autodiscoveryId>12345</api.manager.autodiscoveryId>
<anypoint.platform.client_id>be085956c947426487f50e4ec578d2d6</anypoint.platform.client_id>
<anypoint.platform.client_secret>e4ec517d2d6be085969c947426487f50</anypoint.platform.client_secret>
</properties>
</profile>
<profile>
<id>prod</id>
<properties>
<api.manager.autodiscoveryId>54321</api.manager.autodiscoveryId>
<anypoint.platform.client_id>85956be2d60c94742e4ec6487f50578d</anypoint.platform.client_id>
<anypoint.platform.client_secret>k598u517d2d9te085969c947485287f50</anypoint.platform.client_secret>
</properties>
</profile>
</profiles>
In any case, we can make use of these two profiles in this way: First, by referencing these properties in the MMP configuration:
<plugin>
<groupId>org.mule.tools.maven</groupId>
<artifactId>mule-maven-plugin</artifactId>
<version>4.3.0</version>
<extensions>true</extensions>
<configuration>
<cloudhub2Deployment>
<uri>${anypoint.uri}</uri>
<provider>${anypoint.provider}</provider>
<businessGroupId>${project.groupId}</businessGroupId>
<muleVersion>${app.runtime}</muleVersion>
<applicationName>${project.artifactId}</applicationName>
<replicas>${replicas}</replicas>
<vCores>${vcores}</vCores>
<environment>${env.environment}</environment>
<target>${env.target}</target>
<server>anypoint-exchange-v3</server>
<properties>
<api.manager.autodiscoveryId></api.manager.autodiscoveryId>
</properties>
<secureProperties>
<anypoint.platform.client_id>${anypoint.platform.client_id}</anypoint.platform.client_id>
<anypoint.platform.client_secret>${anypoint.platform.client_secret}</anypoint.platform.client_secret>
</secureProperties>
</cloudhub2Deployment>
</configuration>
</plugin>
mvn clean deploy -DmuleDeploy -Pdev -Dreplicas=1 -Dvcores=0.1