Filtered Resources in Maven

Maven has some really great features. One of them is filtered resources.

Basically, if you use Maven for some time, I’m sure you know what by default everything you put in src/main/resources will be added to the classpath in the resulting artifact (e.g. in the WEB-INF/classes for a *.war archive.) Putting resources in this location is a common way of adding Java properties file to your project.

Now what is interesting: you can use Maven variables in those resource files and they can be swapped into final value during the process-resource phase. You just need to tell Maven that it is not a “regular” resource and that it should be filtered.

As an example: assume you have a following properties file:

src/main/resources/application.properties

app.version = ${version}

And you add the following section to your pom.xml file:

pom.xml

<project>
    <build>
        ...
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>application.properties</include>
                </includes>
                <filtering>true</filtering>
            </resource>
        </resources>
    </build>
<project>

During the prepare-resources phase the application.properties file will be filtered by Maven. The ${...} placeholders will be filled with proper values and the resulting application.properties will be produced and placed somewhere in the target directory. Its content will be something like:

app.version = 0.1.1-SNAPSHOT

You can use variables available out-of-the-box in Maven or some additional ones coming e.g. from the Maven plugins or your own defined in the <properties> pom.xml element. It’s pretty neat if you combine it with Maven Build Number plugin which can add your revision or some custom made build number and save it to your runtime accessible property file.

As a side note, if you define the exact files / directories you want to be filtered and want to treat the rest of the files as regular ones (not filtered) you should instruct Maven to do so. It seems that if you define at least one <resource> element, the default values doesn’t apply anymore. Something like this should do the work:

<project>
    <build>
        ...
        <resources>
            <resource>
                <directory>src/main/resources</directory>
                <includes>
                    <include>application.properties</include>
                </includes>
                <filtering>true</filtering>
            </resource>
            <resource>
                <directory>src/main/resources</directory>
            </resource>
        </resources>
    </build>
<project>

You can see an example of how I used it with Build Number plugin here.