Maven Resource Plugin
The previous chapter of the guide covered basics of Maven Plugins. This chapter explains Maven Resources Plugin which Maven uses to handle the project resources.
Resources are non source files of the project such as properties files, XML configuration files, shell scripts files and also, binary files like images etc., Maven Resources Plugin (plugin prefix resources) copies resource files from source directories to output directory. Apart from the standard resources:help goal, the plugin has three goals:
resources:resources
Copy resources for the main source code to the main output directory.
Always uses the project.build.resources element to specify the
resources to copy.
resources:testResources
Copy resources for the test source code to the test output directory.
Always uses the project.build.testResources element to specify the
resources to copy.
resources:copy-resources
Copy resources of the configured plugin attribute resources
The goal resources:resources binds to process-resources phase and resources:testResources to process-test-resources.
Process Resources
By default, the standard location of the source resources is
src/main/resources
and test resources is src/test/resources
. Let’s
add a database configuration file to the Simple App project and see how
it is processed by Maven. To hold resources, create directories.
$ cd simple-app
$ mkdir -p src/main/resources
$ mkdir -p src/test/resources
Next, add configuration file config.xml
to src/main/resources
and
add test resource file test-config.xml
to src/test/resources
with
following contents.
simple-app/src/main/resources/config.xml
<config>
<url>jdbc:hsqldb:mem:simpledb</url>
<user>admin</user>
<password>secret123</password>
</config>
simple-app/src/test/resources/test-config.xml
<config>
<url>jdbc:hsqldb:mem:testdb</url>
<user>sa</user>
<password></password>
</config>
Finally, run mvn package
.
The directory structure after the build the shown in the screenshot. Lifecycle phase process-resources executes resources:resources goal and it copies src/main/resources/config.xml to output folder target/classes. Similarly, lifecycle phase process-test-resources executes resources:testResources goal and it copies src/test/resources/test-config.xml to output folder target/test-classes.
In package phase, the goal jar:jar includes the classes/config.xml
in
the simple-app-1.0.jar
. By default, the test resources are used only
to run tests and not added to the Jar.
Filters
The Maven Resources Plugin also has features to apply filters to the resource files. Filters replaces the variables denoted by ${…} in resource files with the actual value.
To illustrate resource filtering, assume that, for manageability you
want to centralize the database setting in a properties file. Modify the
config.xml
and test-config.xml
and replace the properties with
variables as follows:
simple-app/src/main/resources/config.xml
<config>
<url>${db.url}</url>
<user>${db.user}</user>
<password>${db.password}</password>
</config>
simple-app/src/test/resources/test-config.xml
<config>
<url>${db.test.url}</url>
<user>${db.test.user}</user>
<password>${db.test.password}</password>
</config>
To place the filter files, create a new directory src/main/filters
and
to it, add a properties file default.properties
.
$ cd simple-app
$ mkdir -p src/main/filters
simple-app/src/main/filters/default.properties
db.url=jdbc:hsqldb:mem:mydb
db.username=admin
db.password=secret123
db.test.url=jdbc:hsqldb:mem:testdb
db.test.username=testuser
db.test.password=
The default.properties
contains main and test database properties as
key-value pairs. We need to tell Maven about the filter file and to do
that, use <build>/<filter> element in pom.xml
simple-app/pom.xml
....
<!-- project build -->
<build>
<filters>
<filter>src/main/filters/default.properties</filter>
</filters>
</build>
....
If we run mvn clean package
, goal copies config.xml as it is without
applying any filters. Because, by default, filtering is disabled. To
apply filter, we have to explicitly turn on the filtering in pom.xml.
simple-app/pom.xml
....
<!-- project build -->
<build>
<filters>
<filter>src/main/filters/default.properties</filter>
</filters>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
....
This turns on the filtering for all resources in the src/main/resources
folder.
Now run mvn clean package
and it, while copying the config.xml to
output directory, replaces the variables denoted by ${…} with the
values from default.properties
.
Since we have not turned on filtering for test resources, the copied test-config.xml still retains the ${..} variables. Modify pom.xml to enable filtering for it too.
simple-app/pom.xml
....
<!-- project build -->
<build>
<filters>
<filter>src/main/filters/default.properties</filter>
</filters>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
<resource>
<directory>src/test/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
....
Surprisingly, in output folder, now you will find two test-config.xml instead of one - target/classes/test-config.xml and target/test-classes/test-config.xml. Something is wrong with the configuration!
Troubleshoot with Effective POM
To explain troubleshooting, we intentionally showed wrong configuration and when something is wrong, first check effective POM.
Generate effective POM as explained in the section called “Effective POM” and there, we get a hint that Maven uses <resources>/<resource> for source resources and <testResources>/<testResource> for test resources.
With the above configuration, both main/resources and test/resources folders are treated as resources while the second one should be treated as test resources. Because of that, the resources:resources goal handles not only the config.xml but also test-config.xml and both lands in target/classes properly filtered.
Because of default definition, the other goal resources:testResources copies test-config.xml to target/test-classes without applying the filters (as by default filtering is disabled).
The proper configuration is in the next listing:
simple-app/pom.xml
....
<!-- project build -->
<build>
<filters>
<filter>src/main/filters/default.properties</filter>
</filters>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
<testResources>
<testResource>
<directory>src/test/resources</directory>
<filtering>true</filtering>
</testResource>
</testResources>
</build>
....
Now filtering is turned on for both the resources and test resources, and the outcome is as expected.
Refer Maven Resources Plugin Documentation for more examples on managing the project resources.
In the next chapter, we see how to override Maven enforced directory structure.