Throughout this book, you will notice references to properties
that can be used in a POM file. Sibling
dependencies in a multiproject build can be referenced using the
${project.groupId}
and
${project.version}
properties, and any part of the
POM can be referenced by prefixing the variable
name with “project
.” Environment
variables and Java System properties can be referenced, as well as
values from your ~/.m2/settings.xml file. What you haven’t yet
seen is an enumeration of the possible property values and some
discussion about how they can be used to help you create portable
builds. This chapter provides such an enumeration.
If you’ve been using property references in your POM, you should also know that Maven has a feature called resource filtering that allows you to replace property references in any resource files stored under src/main/resources. By default, this feature is disabled to prevent accidental replacement of property references. This feature can be used to target builds toward a specific platform and to externalize important build variables to properties files, POMs, or profiles. This chapter introduces the resource filtering feature and provides a brief discussion of how it can be used to create portable enterprise builds.
You can use Maven properties in a pom.xml file or in any resource that is
being processed by the Maven Resource plugin’s filtering
features. A property is always surrounded by ${
and
}
. For example, to reference the
project.version
property, one would write:
${project.version}
Some implicit properties are available in any Maven project, namely:
project.*
Maven Project Object Model. You can use the project.*
prefix to
reference values in a Maven POM.
settings.*
Maven settings. You use the settings.*
prefix to reference values from your Maven
settings in ~/.m2/settings.xml.
env.*
Environment variables such as PATH
and M2_HOME
can be referenced
using the env.*
prefix.
Any property that can be retrieved from the System.getProperty()
method can be referenced as a Maven property.
In addition to these implicit properties, a Maven POM, Maven settings, or a Maven profile can define a set of arbitrary, user-defined properties. The following sections provide more detail on the various properties available in a Maven project.
When a Maven Project Property is referenced, the property name
is referencing a property of the Maven Project Object
Model. Specifically, you are referencing a property of the
org.apache.maven.model.Model
class that is
being exposed as the implicit variable project. When you reference a
property using this implicit variable, you are using simple dot
notation to reference a bean property of the
Model
object. For example, when you reference
${project.version}
, you are really invoking the
getVersion()
method on
the instance of Model
that is being exposed
as project.
The POM is also represented in the pom.xml document present in all Maven projects. Anything in a Maven POM can be referenced with a property. A complete reference for the POM structure is available at http://maven.apache.org/ref/2.0.9/maven-model/maven.html. The following list shows some common property references from the Maven project:
project.groupId
and
project.version
Projects in a large, multimodule build often share the
same groupId
and version
identifiers. When you are declaring
interdependencies between two modules that share the same
groupId
and version
, it
is a good idea to use a property reference for both:
<dependencies> <dependency> <groupId>${project.groupId}</groupId> <artifactId>sibling-project</artifactId> <version>${project.version}</version> </dependency> </dependencies>
project.artifactId
A project’s artifactId
is often used
as the name of a deliverable. For example, in a project with
war
packaging, you will
want to generate a WAR file without the
version identifiers. To do this, you would reference the
project.artifactId
in your
POM file like this:
<build> <finalName>${project.artifactId}</finalName> </build>
project.name
and
project.description
The name and project description can often be useful properties to reference from documentation. Instead of having to worry that all of your site documents maintain the same short descriptions, you can just reference these properties.
project.build.*
If you are ever trying to reference output directories in Maven, you should never use a literal value such as target/classes. Instead, you should use property references to refer to these directories:
project.build.sourceDirectory
project.build.scriptSourceDirectory
project.build.testSourceDirectory
project.build.outputDirectory
project.build.testOutputDirectory
project.build.directory
sourceDirectory
,
scriptSourceDirectory
, and
testSourceDirectory
provide access to the
source directories for the project.
outputDirectory
and testOutputDirectory
provide
access to the directories where Maven is going to put bytecode
or other build output. directory
refers to
the directory that contains all of these output
directories.
There are hundreds of properties to reference in a POM. A complete reference for the POM structure is available at http://maven.apache.org/ref/2.0.9/maven-model/maven.html.
For a full list of properties available on the Maven
Model
object, take a look at the Javadoc for
the maven-model
project here: http://maven.apache.org/ref/2.0.9/maven-model/apidocs/index.html.
Once you load this Javadoc, take a look at the
Model
class. From this
Model
class Javadoc, you should be able to
navigate to the POM property you wish to
reference. If you need to reference the output directory of the
build, you can use the Maven Model
Javadoc to
see that the output directory is referenced via
model.
getBuild().
getOutputDirectory()
;
this method call would be translated to the Maven property reference
${project.build.outputDirectory}
.
For more information about the Maven
Model
module—the module that defines the
structure of the POM—see the Maven Model
project
page at http://maven.apache.org/ref/2.0.9/maven-model.
You can also reference any properties in the Maven Local Settings file, which is usually stored in ~/.m2/settings.xml. This file contains user-specific configuration, such as the location of the local repository and any servers, profiles, and mirrors configured by a specific user.
A full reference for the Local Settings file and corresponding properties is available here: http://maven.apache.org/ref/2.0.9/maven-settings/settings.html.
Environment variables can be referenced with the env.*
prefix. Some interesting environment variables are listed
here:
env.PATH
Contains the current PATH
in which
Maven is running. The PATH
contains
a list of directories used to locate executable scripts and
programs.
env.HOME
On *nix systems, this variable points to a user’s home
directory. Instead of referencing this, you
should use the ${user.home}
property.
env.JAVA_HOME
Contains the Java installation directory. This can point
to either a Java Development Kit
(JDK) installation or a Java Runtime
Environment (JRE). Instead of using this,
you should consider referencing the
${java.home}
property.
env.M2_HOME
While they are available, you should always use the Java
System properties if you have the choice. If you need a user’s home
directory, use ${user.home}
instead of ${env.HOME}
. If you do this, you’ll
end up with a more portable build that is more likely to adhere to
the Write-One-Run-Anywhere (WORA) promise of the
Java platform.
Maven exposes all properties from java.lang.System
. Anything you
can retrieve from System.getProperty()
you
can reference in a Maven property. Table 13-1 lists the available
properties.
System property | Description |
java.version | Java Runtime Environment version |
java.vendor | Java Runtime Environment vendor |
java.vendor.url | Java vendor URL |
java.home | Java installation directory |
java.vm.specification.version | Java Virtual Machine specification version |
java.vm.specification.vendor | Java Virtual Machine specification vendor |
java.vm.specification.name | Java Virtual Machine specification name |
java.vm.version | Java Virtual Machine implementation version |
java.vm.vendor | Java Virtual Machine implementation vendor |
java.vm.name | Java Virtual Machine implementation name |
java.specification.version | Java Runtime Environment specification version |
java.specification.vendor | Java Runtime Environment specification vendor |
java.specification.name | Java Runtime Environment specification name |
java.class.version | Java class format version number |
java.class.path | Java classpath |
java.ext.dirs | Path of extension directory or directories |
os.name | Operating system name |
os.arch | Operating system architecture |
os.version | Operating system version |
file.separator | File separator (“/” on UNIX, “” on Windows) |
path.separator | Path separator (“:” on UNIX, “;” on Windows) |
line.separator | Line separator (“ ” on UNIX and Windows) |
user.name | User’s account name |
user.home | User’s home directory |
user.dir | User’s current working directory |
In addition to the implicit properties provided by the POM, Maven Settings, environment variables, and the Java system properties, you have the ability to define your own arbitrary properties. Properties can be defined in a POM or in a profile. The properties set in a POM or in a Maven profile can be referenced just like any other property available throughout Maven. User-defined properties can be referenced in a POM, or they can be used to filter resources via the Maven Resource plugin. Example 13-1 is an example of defining some arbitrary properties in a Maven POM.
<project> ... <properties> <arbitrary.property.a>This is some text</arbitrary.property.a> <hibernate.version>3.3.0.ga</hibernate.version> </properties> ... <dependencies> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate</artifactId> <version>${hibernate.version}</version> </dependency> </dependencies> ... </project>
This example defines two properties:
arbitrary.property.a
and
hibernate.
version
. The
hibernate.version
is referenced in a dependency
declaration. Using the period character (.
) as a separator in property names is a
standard practice throughout Maven POMs and
profiles. There is nothing special about using a period as a
separator; to Maven, hibernate.version
is just a
key used to retrieve the property value 3.3.0.ga
.
Example 13-2 shows you how to
define a property in a profile from a Maven
POM.
<project> ... <profiles> <profile> <id>some-profile</id> <properties> <arbitrary.property>This is some text</arbitrary.property> </properties> </profile> </profiles> ... </project>
This example demonstrates the process of defining a user-defined property in a profile from a Maven POM. For more information about user-defined properties and profiles, see Chapter 11.
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 that 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 that needs to be configured differently depending on the target deployment environment. For example, a system that reads data from a database has an XML document that 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 use a technology such as Java Naming and Directory Interface (JNDI) to externalize the configuration from the application in an application server, or you can create a build that 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 you have a project that uses the
Spring Framework to configure a BasicDataSource
from the Apache Commons Database Connection Pool (DBCP) project
(http://commons.apache.org/dbcp).
Your project may contain a file in src/main/resources named applicationContact.xml that contains the
XML listed in Example 13-3.
<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
would replace the references to properties such as
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 13-4 shows a POM that
defines the variables referenced in Example 13-3 and activates resource filtering for
every resource under src/main/resources.
<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> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </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 13-3 and the POM from Example 13-4, 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 13-4
also defines a production
profile under the
profiles
/profile
element that 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 13-3 and
the POM from Example 13-4, 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> ...
3.135.198.174