Understanding Maven Resource Filtering


Resource filtering is a feature of Maven that allows us to extract properties from the pom.xml file of our mule apps and use them elsewhere in our project, for example in our properties files or in the log4j2.xml

In this post, we will see how to configure Resource Filtering in Maven, how to extract properties and some examples.


How does Resource Filtering work?

Typically, all the resources in our Mule projects are stored under src/main/resources (and if not you should!). By resources we mean things like, properties files, the log4j2.xml, keystores/trustores, files... in general, here we should put anyy file that our application will use but that should not be compiled.

When we compile our project, Maven will copy these resources to the target folder. By default, Maven won’t allow to change these files. This is when Resource Filtering comes into play. In those situations in which we’d like to inject values coming from the pom.xml file to our properties files, log4j2.xml or any other file we will be filtering the resources.

How to enable Resource Filtering?

Enabling resource filtering means telling Maven which files it should filter. Then, for those files in which we want to filter the pom.xml values, we need to define placeholders or variables with the syntax ${property} to tell Maven which values it should replace. 

For that, first we need to add the following to our pom.xml file:

<project>
...
<build>
...
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
...
</resources>
...
</build>
...
</project>

With that, Maven will take values defined in your pom.xml file and copy them into the files that use the corresponding ${property} placeholder.
Notice there’s a couple of parameters we need to define:
  • filtering - true or false. Allows us to enable/disable the filtering
  • directory - filtering won’t be enabled to all the resources in the project. In this tag we need to specify the folder under which we would like the values to be filtered in. In this case, it’s under src/main/resources.

Example 1: 

Let’s build an app and see how we could filter values from the pom file to a properties file and see if we can see these values in the payload of a flow. 
First, create a new Mule Project and drag and drop to the canvas an HTTP listener and a Transformation.


Next, let’s modify the pom file to include the resource filtering configuration:

<?xml version="1.0" encoding="UTF-8"?>
<project>
<groupId>com.mycompany</groupId>
<artifactId>resources-filtering</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>mule-application</packaging>

<name>resources-filtering</name>

<properties>
<app.runtime>4.6.1</app.runtime>
...
</properties>

<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
...
</resources>
...
</build>
...
</project>

Create a properties file called properties.yaml under the folder src/main/resources. We’ll take some of the contextual information of the app in the pom file and bring it to the properties file. For that copy the following content in the properties file:

# Properties file
appName: "${project.name}"
appVersion: "${project.version}"
runtime: "${app.runtime}"

One thing you’ll notice is that, to reference the values under the properties element of the pom file, like in this case app.runtime, we can omit the properties parent element. So instead of referencing the whole path ${project.properties.app.runtime} we can simply add ${app.runtime}.

After that, go to the Global Elements tab and create a new Configuration Properties element pointing to the properties,yaml file


And lastly, let’s configure the Transformation element in our flow to include these values in the response of our endpoint. Paste the following into the Output of the Transoformation:

%dw 2.0
output application/json
---
{
"appName": p('appName'),
"appVersion": p('appVersion'),
"runtime": p('runtime')
}

Run the project and once it’s deployed send a request to the /maven endpoint. We’ll see that we are getting the values from pom file:


Voila!

Can we be more granular?

By default, with the filtering configuration we’ve seen in the previous example, this filtering will apply to all files under src/main/resources. But there might be situations in which there are files that use the same syntax as a property but which should not be replaced. In those cases, the maven resource filtering plugin allows us to specify which files are filtered and which files are not. 
For that we’ll use the <includes> and <excludes> tags

Example 2:

For example, in the previous scenario, let’s say we want to make sure that we are filtering the values of the pom file only to the properties file and not to the rest of files under src/main/resources. 
Let’s add another properties file under src/main/resources. Name it properties- and pick up just one property:

name: "${project.name}"

Go to the Global Elements tab and a new Configuration Properties element pointing to the properties-2,yaml file
Modify the Transformation element to pick up values from the second properties file:

%dw 2.0
output application/json
---
{
"appName": p('appName'),
"appVersion": p('appVersion'),
"runtime": p('runtime'),
"name": p('name')
}

Keep for now the previous pom file:

<?xml version="1.0" encoding="UTF-8"?>
<project>
<groupId>com.mycompany</groupId>
<artifactId>resources-filtering</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>mule-application</packaging>

<name>resources-filtering</name>

<properties>
<app.runtime>4.6.1</app.runtime>
...
</properties>

<build>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
...
</resources>
...
</build>
...
</project>

If we run the project we’ll see that now Maven is filtering the values to both properties files. Send a request to the /maven endpoint to verify:

 

Now, let’s be more granular and set up the resource filtering only to our first properties file.
We’d configure the pom file like this:


<?xml version="1.0" encoding="UTF-8"?>
<project>
<groupId>com.mycompany</groupId>
<artifactId>resources-filtering</artifactId>
<version>1.0.0-SNAPSHOT</version>
<packaging>mule-application</packaging>

<name>resources-filtering</name>

<properties>
<app.runtime>4.6.1</app.runtime>
...
</properties>

<build>
<resources>
<!-- Enable filtering for specific resources -->
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>properties.yaml</include>
</includes>
</resource>
<!-- Disable filtering for everything else -->
<resource>
<directory>src/main/resources</directory>
<filtering>false</filtering>
<excludes>
<exclude>properties.yaml</exclude>
</excludes>
</resource>
...
</resources>
...
</build>
...
</project>

Run the project and send a request. Now the response should be:


Now we can see that the values of the pom file are filtered only to one of the properties file.
Previous Post Next Post