Mulesoft development fundamentals is a blog series that takes you through various aspects of Mulesoft development from “how to structure your Mule code” to “Things to cater to when you deploy to production”.
This is an attempt to share the expertise that we have gained after working with several Mulesoft enterprise clients.
This read will take you through the best practices of structuring your Mule project code. Although whenever we create a new Mule project in Anypoint Studio, it generates a default project for us to work on, there is always something extra that we can do to make life easier. Structuring your mule code brings in advantages like:
- Ease of building CI/CD pipeline since all the Mule projects have the same structure
- More maintainability for the applications as it becomes easier for any engineer to pick up things
- Less reliance on Knowledge Transfer sessions as people would know where to find what details of the project
- The project itself contains all the information required to get it up and running
We will be going through different folders in a Mule project and see how to get them organized. A sample template project that gets you started with all the best practices mentioned here can be found at https://github.com/Integral-Zone/Mule4-API-Implementation-Template. Let’s crack on
Core Structure — src/main/mule
src/main/mule is the place where all Mule configuration XML files sit. The autogenerated code in Anypoint Studio gives a plain structure but when applications become complex, organizing files into different folders makes a lot of sense.
Common Files in src/main/mule/common
This folder is supposed to have two or more files. Here is what they are:
- global.xml: This file is supposed to contain all the configurations that a mule application will have, be it from HTTP request/listener configs to property config to external sys configs(S3 or AMQ etc.). This file should not have any flows in it.
- common.xml: This file contains all the flows that are common to all the APIs/different streams of work that is being implemented in the project. In case this common file gets too big in a very complicated application, it makes sense to have different common files like <use>-common.xml but generally, a single common.xml file is sufficient for avg size projects. E.g. a file containing logic to call an external API which requires multi step authentication. This logic can be shared by all the APIs and the can be put in a different common file called auth-common.xml in case common.xml already has 10 flows doing other things.
- Error-handler.xml: This file is responsible for global/common error handling across the application.
API Specific files in src/main/mule/<API Name>-<version>
A Mule app may not necessarily contain only one API in it. It is a good practice to club small APIs together to reduce cost. In cases where multiple APIs are clubbed together OR when a complex application is developed, different APIs or functions should be organized in different folders.
e.g. an app that clubs employee and hr API, here is an example of how the files should be organized:

Every different API file is present in a different folder and each folder has an api-name-router.xml file which contains Api-Kit router and other files that contain different business subjects of the API in dedicated files.
Resources — src/main/resources
Properties in src/main/resources/properties
Properties Folder:

This folder contains all the env specific properties for your Mule application. These should be included in the application using ${mule.env} to dynamically reference a property file based on env. This image captures an example of the same. Encrypted and plain text properties should be stored in separate files.
This should be separated by ${mule.env}-properties.yaml and ${mule.env}-secure-properties.yaml.
There is also a need to have common-properties.yaml which will store properties that span across environments e.g. HTTP port number, logger configuration, etc. HTTP listener configuration should be shared among all APIs
It is important to note that in a multi api application, property name should follow the same naming conventions across environment specific properties and common properties. All properties for a particular api should start with that API name-version e.g.
api-name-one-v1: sfdc: username: “admin“
APIs in src/main/resources/api
API Folder:

RAML should always be included using a dependency in pom.xml via exchange. The above example shows a simple use case for the purpose of this blog. In case the application contains only one API, then the entire RAML can be stored directly in resources/api. For a multi API app, each API RAML should be stored in its own dedicated folder.(Please note that downloading and storing RAML file in mule application is not the recommended approach)
Certs in src/main/resources/certs
Certs Folder:

Certificates for all environments to be stored in resources/cert. For better control over certificates and their lifecycle, it is recommended to inject certificates via CICD pipelines.
Dataweave files in src/main/resources/dwl
DWL Folder:

All the dataweave scripts should be stored in resources/dwl. These should further have more folders to contain specific dwl files for different business use-cases/APIs. Just like mule configuration XML files, it makes sense to keep all common dwl functions in resources/dwl/common for reuse.
Testing — src/test
Munit files in src/test/munit
Munit files in src/test/munit should follow the same structure as present in src/main/mule. This ensures that tests for specific API or business use-case sit in similar folders in configuration XML and Munit tests.
Postman Collection and Sample payloads in src/test/resources
src/test/resources should contain all the sample payloads used in:
- Munit testing
- Creating metadata and examples in Transform message
- Any extra example file
In conjunction with the sample payloads, src/test/resources should definitely contain a postman collection per API which should contain all the possible requests for the APIs per env. It’s a good practice to create different folders per environment in the collection. These should all be stored in as test/resources/postman-collections/<api-name>-<version>/<api-name>-<version>.postman_collection.json This ensures that any new developer coming will have a starting point to test the application and hit different endpoints in different environments.
ReadMe File
In addition to everything above, a readme.md file which gives some information on what is the project about, which APIs does it include, how to get started, what are the runtime parameters to be passed etc. should be added in the project core.
Things to cater in POM.xml
Common error handler library
Mulesoft catalyst project in GitHub has a common error handler library that can be used to define all the common error codes in a single place. This component can be placed inside the global error handler which will ensure that all the errors generated in the application comply with the same JSON format. This error-handler-plugin also allows adding of custom error types in its configuration.
Below is the snippet that should be added in your Mule project to include this if you choose to use it:
<dependency> <groupId>${orgId}</groupId> <artifactId>common-error-handler</artifactId> <version>${version}</version> <classifier>mule-plugin</classifier> </dependency>
This is the link to error-handler-plugin which has all the details to use and publish it to Anypoint Exchange. There is also a dwl file which can contain mapping for all the custom errors that need to be added to this plugin. This has been included in the template and can be found at src/main/resources/dwl/errors/customErrors.dwl
JSON Logger
Default Mule logger publishes limited information that too as a string when used. Although it is easy to change the format from String to JSON using log4j2 configuration but adding additional information is always a pain point. Mule JSON logger(not an officially release connector) solves this problem by introducing a logger connector that can print as much information as possible in JSON format. This prints information like correlationId, location information, optionally printing payload, sending logs directly to Anypoint MQ or any other JMS etc.
Here is a link to JSON logger that contains all the details on how to publish this connector to Anypoint Exchange and use it in your project.
API RAML from Anypoint Exchange
The API RAML resides in src/main/resources/api. Manually downloading it from Anypoint Exchange and using it in your project is an easy thing to do but keeping it updated to the latest code in Anypoint Exchange can be a challenge. A best practice would be to include RAML as a dependency in the project’s POM so that it gets freshly downloaded every time RAML is updated. Below is a snippet of dependency of how to do it.
<dependency> <groupId>${orgId}</groupId> <artifactId>api-name</artifactId> <version>1.0.1</version> <classifier>raml</classifier> <type>zip</type> </dependency>
Hope this was helpful, follow this space for more such blogs on Mulesoft Development Fundamentals.
End Note
Hope you found this article interesting, do drop us a comment below with your inputs, views, and opinions regarding Mulesoft Development Fundamentals: Mule Project Structure
Also, if you are interested in learning more about an exciting new code quality product that reduces your Mule project costs by 79%, follow the below link :