You can use Maven to perform variable replacement on project
resources. When resource filtering is activated, Maven will scan resources
for references to Maven property references surrounded by
${ and }. When it finds these
references it will replace them with the appropriate value in much the
same way the properties defined in the previous section can be referenced
from a POM. This feature is especially helpful when you
need to parameterize a build with different configuration values depending
on the target deployment platform.
Often a .properties file or an
XML document in src/main/resources
will contain a reference to an external resource such as a database or a
network location which needs to be configured differently depending on the
target deployment environment. For example, a system which reads data from
a database has an XML document which contains the
JDBC URL along with credentials for
the database. If you need to use a different database in development and a
different database in production. You can either use a technology like
JNDI to externalize the configuration from the application in an
application server, or you can create a build which knows how to replace
variables with different values depending on the target platform.
Using Maven resource filtering you can reference Maven properties
and then use Maven profiles to define different configuration values for
different target deployment environments. To illustrate this feature,
assume that you have a project which uses a the Spring Framework to
configure a BasicDataSource from the Commons DBCP project. Your
project may contain a file in src/main/resources
named applicationContact.xml which contains the
XML listed in Example 9.3, “Referencing Maven Properties from a Resource”.
Example 9.3. Referencing Maven Properties from a Resource
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-2.5.xsd"> <bean id="someDao" class="com.example.SomeDao"> <property name="dataSource" ref="dataSource"/> </bean> <bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="${jdbc.driverClassName}"/> <property name="url" value="${jdbc.url}"/> <property name="username" value="${jdbc.username}"/> <property name="password" value="${jdbc.password}"/> </bean> </beans>
Your program would read this file at runtime, and your build is
going to replace the references to properties like
jdbc.url and jdbc.username with the
values you defined in your pom.xml. Resource filtering is disabled by
default to prevent any unintentional resource filtering. To turn on
resource filter, you need to use the resources child element of the build
element in a POM. Example 9.4, “Defining Variables and Activating Resource Filtering”
shows a POM which defines the variables referenced in
Example 9.3, “Referencing Maven Properties from a Resource” and which activates resource filtering
for every resource under src/main/resources.
Example 9.4. Defining Variables and Activating Resource Filtering
<project>
...
<properties>
<jdbc.driverClassName>
com.mysql.jdbc.Driver</jdbc.driverClassName>
<jdbc.url>jdbc:mysql://localhost:3306/development_db</jdbc.url>
<jdbc.username>dev_user</jdbc.username>
<jdbc.password>s3cr3tw0rd</jdbc.password>
</properties>
...
<build>
<resources>
<resource>src/main/resources</resource>
<filtering>true</filtering>
</resources>
</build>
...
<profiles>
<profile>
<id>production</id>
<properties>
<jdbc.driverClassName>oracle.jdbc.driver.OracleDriver</jdbc.driverClassName>
<jdbc.url>jdbc:oracle:thin:@proddb01:1521:PROD</jdbc.url>
<jdbc.username>prod_user</jdbc.username>
<jdbc.password>s00p3rs3cr3t</jdbc.password>
</properties>
</profile>
</profiles>
</project>
The four variables are defined in the properties
element, and resource filtering is activated for resources under
src/main/resources. Resource filtering is deactivated
by default, and to activate it you must explicitly set
filtering to true for the resources
stored in your project. Filtering is deactivated by default to prevent
accidental, unintentional filtering during your build. If you build a
project with the resource from Example 9.3, “Referencing Maven Properties from a Resource” and the
POM from Example 9.4, “Defining Variables and Activating Resource Filtering” and if you list the contents of
the resource in target/classes, you should see that it contains the
filtered resource:
$ mvn install ... $ cat target/classes/applicationContext.xml ... <bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="com.mysql.jdbc.Driver"/> <property name="url" value="jdbc:mysql://localhost:3306/development_db"/> <property name="username" value="dev_user"/> <property name="password" value="s3cr3tw0rd"/> </bean> ...
The POM in Example 9.4, “Defining Variables and Activating Resource Filtering” also
defines a production profile under the
profiles/profile element which overrides the default
properties with values that would be appropriate for a production
environment. In this particular POM, the default values
for the database connection are for a local MySQL database installed on a
developer's machine. When the project is built with the production profile
activated, Maven will configure the system to connect to a production
Oracle database using a different driver class, URL, username, and
password. If you build a project with the resource from Example 9.3, “Referencing Maven Properties from a Resource” and the POM from Example 9.4, “Defining Variables and Activating Resource Filtering” with the production profile
activated and if you list the contents of the resource in target/classes,
you should see that it contains the filtered resource with production
values:
$ mvn -Pproduction install ... $ cat target/classes/applicationContext.xml ... <bean id="dataSource" destroy-method="close" class="org.apache.commons.dbcp.BasicDataSource"> <property name="driverClassName" value="oracle.jdbc.driver.OracleDriver"/> <property name="url" value="jdbc:oracle:thin:@proddb01:1521:PROD"/> <property name="username" value="prod_user"/> <property name="password" value="s00p3rs3cr3t"/> </bean> ...
