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>
Maven Resources Plugin - process resources

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.