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.

Global Elements view in Anypoint Studio with one HTTP Listener config

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.

Configuration XML view in Anypoint Studio with one HTTP Listener config and one flow

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.

Configuration XML view from both test.xml and global.xml files

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

Project files and folders structure showing the new properties files

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 value local. You should create this env property in each of your environments to match the properties file name. For example, dev to match dev.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 with local and the file will end up being local.properties. The same will happen with the other environments as long as you create the env 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

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.

Get the latest Salesforce Developer blog posts and podcast episodes via Slack or RSS.

Add to Slack Subscribe to RSS