In software development, there are many paths to arrive at the same place, solution-wise. However, not all paths will be the most efficient or the best ones for a particular solution. As developers, we are not only responsible for creating functionality, but we also have to make our code in a way that is easier for other developers to continue building upon. And that’s our focus for today.
In this post, you’ll learn some best practices that are widely applied by MuleSoft developers everywhere. These will help you save development time or make sure there are no security breaks within your Mule apps.
Best practice #1: Keep global elements in a separate file
Global Elements (or Global Configuration Elements) are those configurations that you can see under the Global Elements view in Anypoint Studio when you’re developing a Mule application. For example, the configuration for an HTTP Listener is shown below.
You can also spot them from the XML view because they are located outside of a <flow>
tag and are normally located at the top of the file.
These elements are visible throughout the whole Mule application, not just within their own Mule configuration file. The problem comes when the project has several files, each with global elements, because these elements can be referenced from any Mule configuration file, which makes them hard to locate within the project.
The best practice to avoid this issue is to have just one dedicated Mule configuration file that contains all the global elements. This way, you won’t have to jump from file to file to try to find a specific element. You can simply open this one file that contains all of them.
A lot of people name this file global.xml
to make it easier to spot. If you already have a project with global elements in different files, you can simply cut and paste the elements from the other files into this new file.
Now, every time you create a new global element, you just have to do it from the global.xml
file and reference it from any other Mule configuration file needed.
Note: If you’re working with multiple associated Mule projects hosted on a customer-hosted environment, you can add the global configuration in a domain project. For now, we are focusing on a single Mule project.
Best practice #2: Create a properties file per environment
If you’re working on a big project, you will inevitably have to work in different environments. For example, local
, dev
, qa
, prod
, and so on. At least, you will have a local
environment (from your local computer) and a dev
environment (from the cloud service). Because of this, there are different configuration properties needed for each environment, such as a different database URL for the qa
and prod
environment.
To solve this issue without having to change anything in the code, it’s a best practice to create a separate properties file for each one of your environments. Let’s see an example of the HTTP Listener config we just saw in the previous point. Our current configuration looks like the following.
We don’t want to keep the host
and port
as hardcoded values because these may change depending on the environment. Let’s create two files under src/main/resources
:
dev.properties
local.properties
Now let’s add the following on each file.
After that, you will have to change the hardcoded values from the HTTP Listener config to reference these new properties using the syntax ${property}
. Like so:
Finally, add the following configurations to the global.xml
file, so we can correctly reference these new properties files depending on the environment.
- First, we are creating a global property called
env
with the valuelocal
. You should create thisenv
property in each of your environments to match the properties file name. For example,dev
to matchdev.properties
. - Next, we are telling the app to take the properties from the file that matches
${env}.properties
. If we run this in local,env
will be replaced withlocal
and the file will end up beinglocal.properties
. The same will happen with the other environments as long as you create theenv
property correctly.
Once all this configuration is in place, you can modify the property values directly from the properties files. For example, you could change the http.port
to be 8082
in local but leave the 8081
for dev.
You can continue adding more properties to these files and reference them from other connectors or global elements to avoid hardcoding values directly in the code and change them accordingly per environment.
Best practice #3: Always encrypt and hide your secured properties
In the previous example, we created two properties: http.host
and http.port
. Neither of these were secured properties because the values do not show sensitive information. An example of a secured property would be a password to access Salesforce or a database.
In MuleSoft, there is a tool to encrypt your properties. Please see Encrypt Properties Using the Secure Properties Tool for detailed information. You will also need to configure your files using the Mule Secure Configuration Properties Extension module. Please see Configure the File in the Project for detailed information.
For example, let’s say we encrypted a password and this is the value we ended up with: HbsuWJRjiubchmzQREGdsA==
. Now we have to take that value and add the syntax ![encryptedValue]
to our properties files. We will end up with something like the following.
After that, we can now reference this property from a connector or a configuration, just as we did before. The only difference is that you need to add the secure::
prefix to the property. Like so:
You can add an extra layer of security by hiding your secured properties from user interfaces like Runtime Manager. To do this, you need to add the secureProperties
field to your project’s mule-artifact.json
and include the name of the properties you want to hide from the UI. For example:
Now, when you deploy this Mule application into CloudHub, your password
property’s value will always be hidden!
Conclusion
There are a lot of things that are not always mandatory for an application to run correctly. For example, you don’t have to create a global
file to keep your global elements. However, these are best practices for a reason. They have been proven to help you save time while developing your Mule applications or to increase security to avoid attacks.
To summarize:
- Create a
global.xml
file to keep all your global elements. This will save development time when trying to locate specific elements. - Don’t hardcode the connectors/configurations values. Instead, create properties files to keep these and reference the properties from the connectors/configurations. Create one properties file per environment to use different values accordingly.
- Raise your app’s security by encrypting your secured properties and hiding them from unwanted attention.
Further resources
- How to set up your global elements and properties files in Anypoint Studio
- How to secure properties before deployment in Anypoint Studio
- Secure Configuration Properties
About the author
Alex Martinez was part of the MuleSoft Community before joining MuleSoft as a Developer Advocate. She founded ProstDev to help other professionals learn more about content creation. In her free time, you will find Alex playing Nintendo or Playstation games and writing reviews about them! Follow Alex on LinkedIn or in the Trailblazer Community.