Вы находитесь на странице: 1из 85

Setting Up a Project Using Ant

Ant in the Build Process


Ant is a popular and widely used open source build tool, written in Java. Indeed, it is
probably the most widely used build tool in the Java world. It is supported by virtually
all modern IDEs, and (being a Java application) runs on almost any Java-riendly
platorm.
In a nutshell, Ant helps you transorm the source code, libraries, and other iles that
ma!e up your pro"ect into a deliverable sotware pac!age. And, more importantly, it
helps you do this in an orderly, repeatable manner. I you design your build script well,
you can also ensure that it will behave the same way on any machine. #his leads the
way to automatic builds, which can be run on a remote machine with little or no human
intervention.
Ant is a highly le$ible tool%you can ma!e it do pretty much anything you want.
&owever, this le$ibility can come at a cost o comple$ity. 'ood Ant build scripts are
written in a way that will be easy to read and maintain in a year(s time.
Features of Apache Ant
Ant is the most complete Java build and deployment tool available.
Ant is platorm neutral and can handle platorm speciic properties such as ile separators.
Ant can be used to perorm platorm speciic tas!s such as modiying the modiied time o
a ile using )touch) command.
Ant scripts are written using plain *+,. I you are already amiliar with *+,, you can
learn Ant pretty -uic!ly.
Ant is good at automating complicated repetitive tas!s.
Ant comes with a big list o predeined tas!s.
Ant provides an interace to develop custom tas!s.
Ant can be easily invo!ed rom the command line and it can integrate with ree and
commercial IDEs
Installing Ant
It is assumed that you have already downloaded and installed Java Development .it (JD.) on
your computer

Apache Ant is distributed under the Apache /otware ,icense, a ully-ledged open source
license certiied by the open source initiative.
#he latest Apache Ant version, including ull-source code, class iles and documentation can be
ound at http://ant.apache.org.
1. Ensure that the JA0A1&2+E environment variable is set to the older where your JD. is
installed.
3. Download the binaries rom http455ant.apache.org
6. 7n8ip the 8ip ile to a convenient location using 9in8ip, win:A:, ;-8ip or similar tools, say
c4< older.
=. >reate a new environment variable called A?#1&2+E that points to the Ant installation
older, in this case c4<apache-ant-@.;.A-bin older.
B. Append the path to the Apache Ant batch ile to the CA#& environment variable. In our case
this would be the c4<apache-ant-@.;.A-bin<bin older
2nce this is done, you should be able to run Ant rom the command line4
D Ant -version
Apache Ant version @.;.A compiled on July @@ 3AA;
Introduction to Ant
Ant is an e$tremely powerul tool, and e$perienced users can really ma!e it sing.
9e will start o simply, going through how to set up a small Java pro"ect with Ant.
Basic Ant Concepts
Ant build iles are written in *+,, using a -uite readable set o tags. #he overall struc-
ture o an Ant ile is relatively straightorward and spontaneous. An Ant build ile describes
how to build one (and only one) project. A build pro"ect is made up o targets and tasks.
A target is a goal that you want your build process to achieve. /uch a goal might be to
compile your application code, run your tests, or prepare a production-ready release
pac!age. Eou can (and usually do) deine several targets in your build ile, which you
may run on dierent occasions.
A target can also depend on other targets. #his lets you ensure that certain targets are
always e$ecuted beore others. For e$ample, you might want to ensure that your unit
test(s target is always run beore you prepare a new release. Eou do this by declaring
dependencies between your targets.
A task lets you deine a piece o wor! you want done. #his might be compiling some
Java source code using javac, running a set o unit tests using J7nit, or generating a
production-ready JA: ile using the jar utility. #his is where the wor! actually gets
done. For e$ample, the junit tas!, which runs J7nit test cases, is an op-
tional tas! because it re-uires the J7nit library to be supplied separately.
Finally, Ant allows you to deine and use a set o properties. In Ant, a property can be
used as a way to ma!e your build script simpler and easier to understand, and also to
access system-level properties such as user.dir (the current wor!ing directory) or
os.name (the name o the operating system).
.
A Simple Ant Build File
Directory structure for our project
Directory
src
test
lib
build
build5classes
Contents
Application source code
7nit test code
Cro"ect dependencies
Any iles generated by the build process
>ompiled Java classes
build5test-classes >ompiled unit tests
dist Distribution iles, such as bundled JA: or 9A: iles
&aving a clean, well-deined directory structure is important or any pro"ect, and is
particularly important i you are using a tool li!e Ant. A clear directory layout ma!es
the build script easier to write and understand. /eparating compiled classes rom source
code, or e$ample, ma!es it easier to do a clean recompile simply by deleting the target
directory, and ma!es it easier to place source code (and only source code) under version
control.
7sing a lib directory to store your dependencies is one commonly used approach in
Ant pro"ects, though it is not the only solution to this problem.
#his is not the only way to store dependencies. Indeed, !eeping them in the lib direc-
tory may mean that your JA:s end up being stored in your version control system. #his
is not always ideal. +aven uses a dierent approach, where JA: iles
are stored on a central repository, and dependencies are listed in the build ile, instead
o in one o the pro"ect directories.
+aven uses a similar standardi8ed directory structure which can also
be used or Ant pro"ects.
For our irst e$ample, we will be wor!ing with a simple one-class application that
displays some inormation about the installed J0+ and operating system. #his re-
mar!ably useul piece o code is shown here4
pac!age com.it.ta$calculatorG
public class +ain H
public static void main(/tringIJ args) H
/tring "vm K /ystem.getCroperty(L"ava.versionL)G
/tring os?ame K /ystem.getCroperty(Los.nameL)G
/tring os0ersion K /ystem.getCroperty(Los.versionL)G
/ystem.out.println(L:unning Java L M "vm
M L on L M os?ame
M L (version L M os0ersion M L)L)G
N
N
?ow let(s see how you could use Ant to build this application. At this stage, we "ust
want to compile our code and bundle up a JA: ile containing the compiled classes.
Eou could do this with a build.$ml ile, along the ollowing lines4
OP$ml versionKL@.AL PD
Opro"ect nameKLta$-calculatorL deaultKLpac!ageLD
Otarget nameKLinitLD
Om!dir dirKLbuild5classesL 5D
Om!dir dirKLdistL 5D
O5targetD
Otarget nameKLcompileL dependsKLinitL descriptionKL>ompile Java codeLD
O"avac srcdirKLsrcL destdirKLbuild5classesL5D
O5targetD
Otarget nameKLpac!ageL dependsKLcompileL descriptionKL'enerate JA: ileLD
O"ar destileKLdist5ta$-calculator."arL basedirKLbuild5classesL5D
O5targetD
Otarget nameKLcleanL descriptionKLDeletes generated directoriesLD
Odelete dirKLbuildL 5D
Odelete dirKLdistL 5D
O5targetD
O5pro"ectD
,et(s go through this build ile, and see how it uses the basic concepts we discussed
earlier. ,i!e all Ant build scripts, the root element is called <project>. #he main role
o the <project> element is to act as a container or the other build elements such as
properties, targets, and tas!s. It also lets you deine an (optional) deault target.
Each target uses various built-in Ant tas!s. #he irst thing we need to do in our build
process is create any missing directories. Eou need to ma!e sure these directories have
been created beore compiling your classes. /o, the irst target, called Qinit,R simply
creates the build and dist directories using the mkdir tas!4
Otarget nameKLinitLD
Om!dir dirKLbuild5classesL 5D
Om!dir dirKLdistL 5D
O5targetD
9e don(t need to create the QbuildR directory beore the Qbuild5classesR directory be-
cause Ant will do this automatically or us.
?e$t we need to compile our classes. #he QcompileR target uses javac (or, more pre-
cisely, the javac Ant tas!) to compile the source code in the src directory and place the
compiled classes in the build5classes directory4
Otarget nameKLcompileL dependsKLinitL descriptionKL>ompile Java codeLD
O"avac srcdirKLsrcL destdirKLbuild5classesL5D
O5targetD
#he Qpac!ageR target creates a JA: ile in the dist directory containing all o the com-
piled classes in the build5classes directory4
Otarget nameKLpac!ageL dependsKLcompileL descriptionKL'enerate JA: ileLD
O"ar destileKLdist5ta$-calculator."arL basedirKLbuild5classesL5D
O5targetD
Finally, the QcleanR target simply deletes the generated directories using the delete tas!4
Otarget nameKLcleanL dependsKLinitL descriptionKLDeletes generated directoriesLD
Odelete dirKLbuildL 5D
Odelete dirKLdistL 5D
O5targetD
Running Ant
9e are now ready to run this build script. Eou can do so by running Ant in the root
directory o your pro"ect. I you run Ant with no arguments, Ant will invo!e the deault
target, which is Qpac!ageR or this pro"ect4
$ ant
Suildile4 build.$ml
init4
Im!dirJ >reated dir4 5home5wa!aleo5pro"ects5"pt-sample-code5ant-demo5build5classes
Im!dirJ >reated dir4 5home5wa!aleo5pro"ects5"pt-sample-code5ant-demo5dist
compile4
I"avacJ >ompiling @ source ile to 5home5wa!aleo5pro"ects5"pt-sample-code5ant-demo
5build5classes
pac!age4
I"arJ Suilding "ar4 5home5wa!aleo5pro"ects5"pt-sample-code5ant-demo5dist
5ta$-calculator."ar
S7I,D /7>>E//F7,
#otal time4 @ second
Alternatively, you can speciy the target you want to run, as shown here with the QcleanR
target4
$ ant clean
Suildile4 build.$ml
init4
clean4
IdeleteJ Deleting directory 5home5wa!aleo5pro"ects5"pt-sample-code5ant-demo5build
IdeleteJ Deleting directory 5home5wa!aleo5pro"ects5"pt-sample-code5ant-demo5dist
S7I,D /7>>E//F7,
#otal time4 A seconds
Eou can also run several targets at the same time, simply by listing them as arguments
on the command line4
$ ant clean compile
Suildile4 build.$ml
clean4
IdeleteJ Deleting directory 5home5wa!aleo5pro"ects5"pt-sample-code5ant-demo5build
IdeleteJ Deleting directory 5home5wa!aleo5pro"ects5"pt-sample-code5ant-demo5dist
init4
Im!dirJ >reated dir4 5home5wa!aleo5pro"ects5"pt-sample-code5ant-demo5build5classes
Im!dirJ >reated dir4 5home5wa!aleo5pro"ects5"pt-sample-code5ant-demo5dist
compile4
I"avacJ >ompiling @ source ile to 5home5wa!aleo5pro"ects5"pt-sample-code5ant-demo
5build5classes
S7I,D /7>>E//F7,
#otal time4 3 seconds
Sy convention, Ant iles are called build.$ml, but you can speciy a dierent build script
using the -f option4
$ ant -f my-special-buildfile.xml
Finally, li!e many tools, you can activate a verbose mode (using the -v command-line
option) to display more details about what Ant is doing. #his can be useul when de-
bugging your build scripts4
$ ant -v
Apache Ant version @.;.A compiled on July @@ 3AA;
Suildile4 build.$ml
Detected Java version4 @.T in4 5usr5lib5"vm5"ava-T-sun-@.T.A.AA5"re
Detected 2/4 ,inu$
parsing buildile 5home5wa!aleo5pro"ects5"ava-power-tools5sample-code5chA@5ant-demo
5build.$ml with 7:I K ile45home5wa!aleo5pro"ects5"ava-power-tools5sample-code5chA@
5ant-demo5build.$ml
Cro"ect base dir set to4 5home5wa!aleo5pro"ects5"ava-power-tools5sample-code5chA@
5ant-demo
...
+ost Ant targets are not designed to be run in isolation. Seore compiling the Java
source code, we need to create the target directories. And we obviously need to compile
the latest version o the source code beore we can generate a new version o the JA:
ile. In other words, there is a precise order in which the targets need to be e$ecuted.
>ertain targets depend on others.
In Ant, you use the depends attribute to declare a target(s direct dependencies4
Otarget nameKLpac!ageL dependsKLcompileL descriptionKL'enerate JA: ileLD
Otarget nameKLcompileL dependsKLinitL descriptionKL'enerate JA: ileLD
In this e$ample, the Qpac!ageR target depends on the QcompileR target to compile the
Java classes, which in turn depends on the QinitR target to prepare the output directories.
In act, the Qpac!ageR target also depends on Qinit,R but we don(t need to list QinitR in
the Qpac!ageR target dependencies because it will automatically be called when the
QcompileR target is e$ecuted. #hese dependencies can be e$pressed as a dependency
graph, as shown in the above igure.
/ome targets can have multiple dependencies. For e$ample, in the ollowing code the
QtestR target directly depends on both the Qunit-testR and the Qintegration-testR targets.
Otarget nameKLtestL dependsKLunit-test, integration-testL descriptionK
L'enerate JA: ileLD
Ant is airly smart about how it handles dependencies. For e$ample, i both the Qunit-
testR and the Qintegration-testR targets depend on the QcompileR target, this target will
only be e$ecuted once.
Documenting Your Project
Documenting build scripts is important, and Ant build iles are no e$ception. ,et
unattended, they can -uic!ly become a nightmare to understand, both or you and
other developers later on.
In addition to traditional techni-ues such as *+, comments, Ant comes with a ew
built-in eatures to help you document your build scripts. #he description attribute lets
you provide a short description or your targets, as shown here4
Otarget nameKLcompileL dependsKLinitL descriptionKL>ompile Java codeLD
O"avac srcdirKLsrcL destdirKLbuild5classesL5D
O5targetD
It is a good idea to use the description attribute or the targets in your build script that
are intended or e$ternal use. Eou can then use the -projecthelp command-line option
to list the main build targets, complete with a brie description. 9ith large build scripts
(and Ant build scripts can become very large), this can be a valuable time-saver4
$ ant -projecthelp
Suildile4 build.$ml
+ain targets4
compile >ompile Java code
pac!age 'enerate JA: ile
clean Deletes generated directories
Deault target4 pac!age
Compiling Your a!a Code in Ant
In Java development, one o the most undamental things that any build script needs
to do is compile your code. In Ant, the <javac> tas! provides a convenient one-stop
shop or Java compilation.
,et(s loo! at a simple use o the <javac> tas!. In the e$ample given above, we use a
simple orm o this tas! to compile the Java classes in the src5main directory, and place
the compiled classes in the build5classes directory4
Otarget nameKLcompileL dependsKLinitL descriptionKL>ompile Java codeLD
O"avac srcdirKLsrcL destdirKLbuild5classesL5D
O5targetD
#his is e-uivalent to e$ecuting the javac tool as shown here4
U javac -noarn -d build!classes src!main
In most real applications, your application will re-uire a set o libraries both to compile
and to run. In Ant pro"ects, these libraries are oten stored (in the orm o JA: iles) in
a directory called lib. 9hen you compile your application, you need to tell Ant where
to ind these libraries.
Ant comes with some very powerul eatures to help you do this. Ant e$cels at deining
and manipulating classpaths and other ile path deinitions. At its simplest, you can use the
<path> tag to identiy a particular
library using the location attribute4
Opath idKL"unit.classpathL locationKLlib5"unit."arL5D
#his path could also be deined in the same way using the path attribute. &owever, in
addition to deining single JA: iles or directories, the path attribute lets you use a more
path-li!e construction using a combination o directory paths and a JA: ile, as shown
here4
Opath idKL"unit.classpathL pathKLbuild5classes4lib5"unit."arL5D
2ne o the nice things about the Ant path-handling eatures is that they are (li!e the
underlying Java ACIs) portable across dierent operating systems. &ere, by convention,
we use 7ni$-style paths containing orward slashes (Q5R). For e$ample, on a 9indows
machine, Ant will automatically translate the above path into Qbuild<classesGlib
<"unit."ar.R
Although this certainly ma!es or more readable build iles, the real advantages o Ant(s
path-handling eatures come into play when you need to manipulate large sets o iles.
#he ollowing e$ample creates a path deinition including all the V."ar iles in the lib
directory4
Opath idKLcompile.classpathLD
Oileset dirKLlibL includesKLV."arL 5D
O5pathD
#his sort o thing is e$actly what you oten need to deine classpaths or real-world Java
builds. Eou can use this classpath in the <javac> tas! using the classpathref attribute,
as shown here4
Otarget nameKLcompileL dependsKLinitL descriptionKL>ompile Java codeLD
O"avac srcdirKLsrcL
destdirKLbuild5classesL
classpathreKLcompile.classpathL 5D
O5targetD
Alternatively, i you don(t thin! you will need this classpath elsewhere in your build
ile, you can embed the <classpath> element directly in the <javac> tas!4
Otarget nameKLcompileL dependsKLinitL descriptionKL>ompile Java codeLD
O"avac srcdirKLsrcL destdirKLbuild5classesLD
OclasspathD
Oileset dirKLlibL includesKLV."arL5D
O5classpathD
O5"avacD
O5targetD
#hese paths actually use a shorthand notation or convenience. Eou can also use em-
bedded tags or a more readable notation, which is useul when many separate classpath
elements are re-uired. #his is also convenient i you want to reuse paths deined else-
where in the build ile. #he <pathelement> tag lets you deine a classpath element using
either a JA: ile, a directory, or even a reerence to another classpath element4
Opath idKLtest.classpathLD
Opath reidKLcompile.classpathL5D
Opathelement locationKLlib5"unit."arL5D
Opathelement pathKLbuild5test-classesL5D
O5pathD
Eou can also use path-li!e e$pressions within the <javac> tas! itsel to tell Ant what
classes to include or which ones should be e$cluded rom the compilation process,
using the includes and excludes attributes. For e$ample, to compile only the classes in
the com.mycompany.myapp.web pac!age (and below), you could do this4
O"avac srcdirKLsrcL destdirKLbuild5classesL includesKLcom5mycompany5myapp5web5VVL 5D
2ne re-uent re-uirement when compiling Java code is to compile or a speciic Java
version. For e$ample, you may use Java T on your development machine, but need to
deploy to an environment where only Java @.= is supported. Eou can ensure that your
Java code is compatible with Java @.=, and that none o the nice Java B syntactic sugar
is used, by setting the source attribute to Q@.=.R /imilarly, you can tell Ant to generate
byte-code compatible with a Java @.= J0+ by speciying the target attribute as Q@.=.R
O"avac srcdirKLsrcL destdirKLbuild5classesL sourceKL@.=L targetKL@.=L 5D
Eou may also need to indicate i you want the source code compiled with debug in-
ormation. Sy deault, this is turned o, but it can come in handy when testing and
debugging your code. #o turn this option on, set the debug attribute to QonR (or QtrueR)4
O"avac srcdirKLsrcL destdirKLbuild5classesL debugKLonL 5D
Despite its name, the <javac> tas! is not tied to the standard /un Java compiler, also
called javac. In act, ans o alternative compilers li!e Ji!es and '>J can use these
compilers, or a number o other more e$otic choices, by speciying the compiler
attribute4
O"avac srcdirKLsrcL destdirKLbuild5classesL compilerKL"i!esL5D
Eou can also deine this value or the entire build ile by setting the build.compiler
property.
As you can see, the <javac> tas! provides a powerul, le$ible tool or Java compilation.
+any o the techni-ues covered here are typical o many Ant tas!s, and we will see
more e$amples o these later on.
Understanding Ant datatypes and properties
Datatype o!er!ie"
2ne o the great advantages Ant has over the alternatives to building and pac!aging Java
applications is that it understands the primary problem domain, that o building Java
pro"ects. +ost steps to build a typical Java pro"ect deal with iles and paths (such as
classpaths). Ant provides datatypes to handle these two concepts natively. Eou can thin! o
an Ant datatype as similar to Java(s own built-in core classes4 data that can be
passed around and provided to tas!s. #he ileset and path datatypes, and several others,
orm the basic building bloc!s o Ant build iles.
>lasspath-related headaches are commonplace in Java development. Ant ma!es dealing
with classpaths much more natural and pleasant than the command-line manual alternative,
and provides or the reuse o deined classpaths wherever needed. For e$ample, compiling
source code re-uires that reerenced classes be in the classpath. A path can be deined once
or compilation with O"avacD, and reused or e$ecution (via O"ava). 2ne o the
conse-uences o classpaths being speciied inside the build ile is that Ant can be invo!ed
without an e$plicitly deined system classpath, ma!ing it easy to install Ant and build a
pro"ect with little or no environmental coniguration.@ Another no less important
conse-uence is that classpaths can be easily and tightly controlled. #his reduces
>,A//CA#& coniguration problems, both or compilation and e$ecution.
A set o iles is a common entity to manipulate or such tas!s as compiling, pac!aging,
copying, deleting, and documenting. Deining a ileset o all ."ava iles, or e$ample, is
straightorward4
<fileset dir="src" includes="**/*.java" id="source.fileset"/>
Sy providing an id attribute, we are deining a reerence. #his reerence name can be used
later wherever a ileset is e$pected. For e$ample, copying our source code to another
directory using the previously deined source.fileset is
<copy todir="backup">
<fileset refid="source.fileset"/>
</copy>
Property o!er!ie"
Ant(s property handling mechanism allows or build ile e$tensibility and reusability by
parameteri8ing any string-speciied item. #he control users get over build iles can be
dramatically increased with the techni-ues shown in this chapter. For e$ample, changing a
build to use a dierent version o a third-party library, perhaps or testing purposes, can be
made as trivial as this4
ant -Dstruts.jar=/home/ant/newstruts/struts.jar
In this case, struts.jar represents an Ant property, and in our build ile, we reer to it
with special synta$: ${struts.jar}. A !ey eature o an Ant property is its
immutabilityG it resists change once set.
FI#$S$%S
Implicitly, all build processes will operate on sets o iles, either to compile, copy, delete,
or operate on them in any number o other ways. Ant provides the ileset as a native
datatype. It is diicult to imagine any useul build that does not use a ileset. /ome tas!s
support paths, which implicitly support ilesets, while other tas!s support ilesets directly
and this distinction should be made clear in each tas!(s documentation.
A ileset is a set o iles rooted rom a single directory. Sy deault, a ileset speciied with
only a root directory will include all the iles in that entire directory tree, including iles in
all subdirectories recursively. For a concrete running e$ample that will demonstrate
ileset eatures as we discuss them, let(s copy iles rom one directory to another4
<copy todir="new_web">
<fileset dir="web"/>
</copy>
In its current orm, all iles rom the web directory are copied to the new1web directory.
#his e$ample will evolve into copying only speciic iles, altering them during the copy
with to!en replacement, and lattening the directory hierarchy in the new1web directory.
Fileset e&amples
During a build, you oten need to build a ileset by including or e$cluding sets o iles. A
ew e$amples o typical ilesets ollow.
Include all JA: iles in the lib directory (nonrecursive, no subdirectories are considered)4
<fileset dir="lib">
<include name="*.jar"/>
</fileset>
Include all ."ava iles below the test directory that end with the word Q#estR
<fileset dir="test">
<include="**/*Test.java"/>
</fileset>
All non-J/C pages in the web directory and below4
<fileset dir="web">
<exclude name="**/*.jsp"/>
</fileset>
Sy deault, includes and e$cludes are case-sensitive, but this can be disabled by speciying
casesensitive="false". The <include> and <exclude> elements are called
patternsets.
PA%%$R'S$%S
Filesets accomplish the include5e$clude capability by utili8ing another o Ant(s core
datatypes4 the patternset. A patternset is a collection o ile matching patterns. A patternset
itsel does not reer to any actual iles until it is nested in a ileset and thereore
rooted at a speciic directory. A pattern is a path-matching speciication similar to 7ni$-
and +/-D2/-based ile matching. E$amples o this have already been shown with V."ar
used to represent all iles with the ."ar e$tension in the top directory and
VV5V."sp to represent all iles in the entire directory tree with the ."sp e$tension.
#he pattern matching eatures are as ollows:
V matches 8ero or more characters.
W P matches a single character.
W VV, used as the name o a directory, represents matching o all directories rom
that point down, matching 8ero or more directories.
A pattern ending with a trailing 5 or < implies a trailing VV. Implicitly a OilesetD
holds a patternset, but patternsets can also be speciied independently, allowing or
the reuse o patternsets in multiple ilesets.
Catternset attributes. Including and e$cluding patterns allows ilesets to be deined
precisely to encompass only the iles desired. #he includesile and e$cludesile
adds a level o indirection and e$ternal customi8ation.
Attribute Description
includes Comma-separated list of patterns of fles that must be included. All fles
are
included when omitted.
excludes Comma-separated list of patterns of fles that must be excluded. No fles
(except default excludes are excluded when omitted.
includesfile The name of a fle! each line of this fle is ta"en to be an include pattern.
#ou can specif$ more than one include fle b$ usin% nested
includesfile elements.
excludesfile The name of a fle! each line of this fle is ta"en to be an exclude pattern.
#ou can specif$ more than one exclude fle b$ usin% nested
excludesfile elements.
E$cludes ta!e precedence, so that i a ile matched both an include and e$clude pattern
the ile would be e$cluded. Elements corresponding to these attributes are also available
as child elements o OpatternsetD or increased le$ibility and control.
#he elements are OincludeD, Oe$cludeD, OincludesileD, and Oe$cludesileD.
Each o these elements has a name attribute. For OincludeD and
Oe$cludeD, the name attribute speciies the pattern to be included or e$cluded,
respectively. For the OincludesileD and Oe$cludesileD elements, the name attribute
represents a ile name. Each o these elements has i5unless attributes,
which are covered in the conditional patternset section later in this chapter &ere are some
e$amples o patternsets4
<patternset>
<include name="*.jsp"/>
</patternset>
#he OpatternsetD element is not always e$plicitly speciied when used within a ileset. A
ileset implicitly contains patternsets. 2ur running copy e$ample is shown again using a
patternset to include all J/C iles4
<copy todir="new_web">
<fileset dir="web" includes="**/*.jsp"/>
</copy>
#his is e-uivalent to
<copy todir="new_web">
<fileset dir="web">
<include name="**/*.jsp"/>
</fileset>
</copy>
&ad we speciied "ust V."sp, only the J/C iles in the web directory would have been
copied, but no iles in its subdirectories.
Catternsets may be nested within one another, such as
<patternset>
<include name="**/*.gif,**/*.jpg"/>
<patternset>
<exclude name="**/*.txt,**/*.xml"/>
</patternset>
</patternset>
#his is a contrived e$ample simply demonstrating the nesting capability. #his nesting is
unnecessary in this e$ample, but datatype reerences ma!e the nesting capability
powerul. Catternset nesting is a eature introduced with Ant @.B
S$#$C%(RS
Ant @.B includes a sophisticated new eature, called selectors, orselecting the
ilesincluded in a ileset.
Ants built-in selectors
Selector Description
<filename> &or"s li"e a patternset <include> or <exclude> element to
match fles based on a pattern.
<depth> 'elects fles based on a director$ depth ran%e.
<size> 'elects fles that are less, e(ual, or more than a specifed si)e.
<date> 'elects fles (and optionall$ directories that ha*e been last
modifed before, after, or on a specifed date.
<present> 'elects fles if the$ exist in another director$ tree.
<depend> 'elects fles that are newer than correspondin% ones in
another director$ tree.
<contains> 'elects fles that contain a strin%.
#hese selectors can be combined inside selector containers to provide grouping and
logic. #he containers are <and>, <or>, <not>, <none>, and <majority>.
>ontainers
may be nested inside containers, allowing or the construction o comple$ selection
logic. :ather than detailing every available selector, container, and their options, we
reer you to Ant(s documentation or this inormation. 9e will, however,
provide a couple o e$amples showing how selectors wor!.
#o compare two directory trees and copy the iles that e$ist in one tree but not another
we use a combination o <not> and <present>:
<copy todir="newfiles" includeemptydirs="false">
<fileset dir="web">
<not>
<present targetdir="currentfiles"/>
</not>
</fileset>
</copy>
#he <copy> tas! is copying only the iles rom the web directory that do not e$ist in
the currentiles directory. 7sing the <contains> selector, we can choose only the iles
that contain a certain string:
<copy todir="currentfiles" includeemptydirs="false">
<fileset dir="web">
<contains text="System"/>
</fileset>
</copy>
2nly the iles containing the te$t Q/ystemR in the web directory are copied to the
currentiles directory. Sy deault <contains> is case-sensitive, but can be changed
using casesensitive="no".
All rules must be satisied beore a ile is considered part o a ileset, so when using
selectors in con"unction with patternsets, the ile must match the include patterns, must
not match any e$clude patterns, and the selector rules must test positively.
A <custom> selector enables you to write your own selector logic in a Java class.
FI#%$RC)AI'S A'D FI#%$RR$AD$RS
Crocessing te$t iles has never been so easy with Ant until the introduction, in version
@.B, o Filter>hains and Filter:eaders. A Filter:eader is a simple ilter o te$t input
that can remove or modiy the te$t beore it is output. A Filter>hain is an ordered group
o one or more Filter:eaders. A Filter>hain is analogous to piping output rom
one command to another in 7ni$, with the output o one command being the input to
the ne$t, and so on.
#here are a number built-in Filter:eaders, as shown in table
Ants built-in FilterReaders
FilterReader Description
<classconstants>. +enerates name=value" lines for basic and 'trin%
datat$pe constants found in a class fle.
<expandproperties> ,eplaces Ant propert$ *alues.
<headfilter> -xtracts the frst specifed number of lines.
<linecontains> .nl$ lines containin% the specifed strin% are passed
throu%h.
<linecontainsregexp> .nl$ lines matchin% specifed re%ular expression(s are passed
throu%h.
<prefixlines> All lines ha*e a prefx prepended.
<replacetokens> /erforms to"en substitution, 0ust as fltersets do.
<stripjavacomments> ,emo*es 1a*a st$le comments.
<striplinebreaks> ,emo*es line brea"s, defaultin% to \r" and \n" but
characters
stripped can be specifed.
<striplinecomments> ,emo*es lines be%innin% with a specifed set of
characters.
<tabstospaces> ,eplaces tabs with a specifed number of spaces.
<tailfilter> -xtracts the last specifed number of lines.
*APP$RS
Ant(s mapper datatype is used to match sets o iles with one another. #here are several
built-in mapper types as shown in table. +appers are used by <uptodate>, <move>,
<copy>, and <apply> and several other tas!s. Depending on the mapper type, to
and from attributes may be re-uired.
Identity mapper
#he target ile name maps e$actly to the source ile name. #he to and from attributes
are not used by the identity mapper.
<mapper type="identity"/>
Sy deault, the <copy> tas! uses the identity mapper. #he ollowing two OcopyD
tas!s have the same eect4
<copy todir="new_web">
<fileset dir="web" includes="**/*.jsp"/>
<mapper type="identity"/>
</copy>
<copy todir="new_web">
<fileset dir="web" includes="**/*.jsp"/>
</copy>
Flatten mapper
#he flatten mapper removes all directory path inormation rom the source ile
name to map to the target ile name. The to and from attributes are not used. #he
latten mapper is useul in copying iles rom a nested directory structure into a
single directory eliminating the hierarchy.
#o copy all J/C pages rom the web directory hierarchy into a single lat directory,
the flatten mapper is used in this manner:
<copy todir="new_web">
<fileset dir="web" includes="**/*.jsp"/>
<mapper type="flatten"/>
</copy>
?ote that i multiple iles have the same name in the source ileset, regardless o directory,
only one o them will ma!e it to the destination directoryG it is unspeciied which one it
will be.
*erge mapper
#he target ile name remains i$ed to the to attribute speciied. All source ile names
map to the single target.
<mapper type="merge" to="archive.zip"/>
#he merge mapper is used with <uptodate> in cases where many iles map to a
single destination. For e$ample, many iles are bundled together into a single Xip ile.
A property can be set i the Xip contains all the latest sources:
<uptodate property="zip.notRequired">
<srcfiles dir="src" includes="**/*.java"/>
<mapper type="merge" to="${dist.dir}/src.zip"/>
</uptodate>
/aving time by s!ipping unnecessary steps4 OuptodateD
#o determine i target iles are up-to-date with source iles, Ant provides the OuptodateD
tas!. +ost tas!s (such as O"avacD) deal with source5target out-o-date
chec!ing internally, but there are cases where it is necessary to do this yoursel. For
e$ample, the J7nit test (see chapter = or in-depth coverage) tas! does no dependency
chec!ing and simply runs all tests regardless o whether or not any .class iles were
modiied. /!ipping the unit test target i all the test related iles are up-to-date dramatically
improves build time without sacriicing integrated testing4
<uptodate property="tests.unnecessary">
<srcfiles dir="src" includes="**/*.java"/>
<mapper type="glob" from="*.java" to="${build.dir}/classes/*.class" />
</uptodate>
Deferring the discussion of the +mapper, element for just a moment- this e&ample
is setting the property tests.unnecessary to true if each module from the
source tree is not ne"er than its corresponding .class file. /%his default is changed 0y
specifying a !alue attri0ute.1 %his e&ample is sho"ing a one2to2one mapping from
source file to target file- also ignoring any non2.ja!a files in the source tree. (ther scenarios
ta3e ad!antage of many2to2one mappings or other more comple& mappings
a!aila0le "ith the mappers. Com0ining the use of +uptodate, and conditional targets
is a useful techni4ue to allo" your 0uild file to handle some dependency chec3ing
that tas3s do not.
#he merge mapper in <copy> is not e$tremely useul since all iles get copied to
the same ile, with the last unpredictable ile becoming the sole new ile. #here is one
interesting case, however, that is worthy o mention. I, or e$ample, you have a directory
containing a single ile whose name is not precisely !nown (perhaps with a timestamp
sui$), you can copy this ile to a !nown ile name using the merge mapper:
<copy todir="output">
<fileset dir="data"/>
<mapper type="merge" to="data.dat"/>
</copy>
Assume that there is a single ile in the data directory called data13AA3A3A3.dat, yet
this ile name is dynamically generated. #he use o the merge mapper will copy it to
the output directory with the name data.dat. #his particular techni-ue, remember, is
only useul with ilesets containing a single ile.
Rege&p mapper
#he !ing o all mappers, but over!ill or most cases, is regexp. #he from attribute
speciies a regular e$pression. 2nly source iles matching the from pattern are
considered.
#he target ile name is built using the to pattern with pattern substitutions
rom the from pattern, including \0 or the ull matched source ile name and \1
through \9 or patterns matched with enclosing parenthesis in the from pattern.
In order to use the regexp mapper, a regular e$pression library is needed. #he Ant
documentation reers to several implementations. 9e recommend Ja!arta 2:2,
although JD. @.= comes with an implementation as well and is used by deault i
present. /imply drop the JA: ile or the regular e$pression implementation into
A?#1&2+E5lib to have it automatically recogni8ed by Ant. &ere(s a simple e$ample
having the same eect as the glob mapper e$ample to map all .java iles to
.java.bak iles:
<mapper type="regexp" from="^(.*)\.java$" to="\1.java.bak"/>
E$ample4
<copy todir="new_web">
<fileset dir="web" includes="**/*.jsp"/>
<mapper type="regexp" from="^(.*)\.jsp$" to="\1.jsp.bak" />
</copy>
ADDI%I('A# A'% DA%A%YP$S
9e have covered the Ant datatypes that are re-uently used by Ant tas!s, but there are
everal other datatypes that are used by a smaller number o tas!s.
5ipFileset
Suilding an archive that contains the contents o other archive iles can be accomplished
using the <zipfileset> datat$pe. A <zipfileset> not only allows putting
the contents o one archive inside another, it also provides the capability to prei$
an archives contents within another. For e$ample, when building the 9A: ile or
our search engine application, we incorporate the Javadoc &#+, in an api subdirectory
and our documentation under the help directory. #hese were not the directory
names used during our build process, yet the 9A: ile will have these names in its
structure.
<war destfile="dist/antbook.war" webxml="web.xml">
<classes dir="${build.classes.dir}"/>
.
.
.
<fileset dir="web"/>
<zipfileset dir="${javadoc.dir}" prefix="api" />
<zipfileset dir="${build.dir}/webdocs" prefix="help"/>
</war>
#he tas!s that support the XipFileset datatype are <zip>, <jar>, <war>, and
<ear>.
PR(P$R%I$S
Cerhaps the most important concept to ully understand in Ant is its notion o properties.
Croperties are loosely analogous to variables in that they are mappings between
names and values and, not coincidentally, are very similar conceptually to "ava.
util.Croperties.
Ant properties are typically, depending on the conte$t o their use, denoted by
${property.name}within the build ile. #o e$amine the properties provided
<target name="echo">
<echo message="ant.file = ${ant.file}"/>
<echo message="ant.home = ${ant.home}"/>
<echo message="ant.java.version = ${ant.java.version}"/>
<echo message="ant.version = ${ant.version}"/>
<echo message="basedir = ${basedir}"/>
</target>
#his generates output similar to this4
echo:
[echo] ant.file = C:\AntBook\Sections\Learning\datatypes\properties.xml
[echo] ant.home = c:\AntBook\jakarta-ant-1.5Beta1
[echo] ant.java.version = 1.3
[echo] ant.version = Apache Ant version 1.5Beta1 compiled on April 30 2002
[echo] basedir = C:\AntBook\Sections\Learning\datatypes
Built-in properties
Name Defnition
ant.file The absolute path of the build fle.
ant.home The path to executin% *ersion of Ant2s root director$
. ant.java.version The 134 *ersion Ant detected! currentl$ it can hold the *alues
1.1, 1.2,
1.3, and 1.4
.
ant.project.name The name of the pro0ect that is currentl$ executin%! it is set in the name
attribute of <project>.
ant.version. The *ersion of Ant
basedir The absolute path of the pro0ect5s basedir (as set with the basedir
attribute of 6pro0ect7.
#his e$ample was run with the -f command-line option to speciy a dierent build
ile name as shown in ant.file. Sy the time o publication, many o us will probably
see 1.4 for ant.java.version. #he latest release version o Ant at the time o
writing was version @.B Seta, but it will be an oicial release by the time o publication.
#he basedir property deaults to the path o the current build ile, and can be
changed by speciying basedir on the <project> element or controlled e$ternally
using property overrides as discussed shortly.
Implicitly, all J0+ system properties are provided as Ant properties, allowing valuable
inormation such as the users home directory path and the current username to
be utili8ed as desired. #he J0+ system properties will vary rom platorm-to-platorm,
but there are many that you can rely on, or e$ample
<echo message="user.name = ${user.name}"/>
<echo message="user.home = ${user.home}"/>
<echo message="java.home = ${java.home}"/>
&ere are sample results rom running this code on a 9indows machine:
[echo] user.name = erik
[echo] user.home = C:\Documents and Settings\erik
[echo] java.home = c:\jdk1.3.1\jre
Setting properties "ith the +property, tas3
#he <property> tas! allows build iles to deine their own sets o custom properties.
#he most common variants o creating properties are
W ?ame5value attributes
W ,oad a set o properties rom a properties ile
W ,oad environment variables
Setting and using a simple property
A typical development-versus-production build dierence is in the enabling or disabling
o debug mode on compilation. /ince we want a single build ile with a single
<javac> tas!, we use a property to parameteri8e it. 9e deine a property named
build.debug and set its value to on (the value that <javac> uses on its debug
atribute).
<property name="build.debug" value="on"/>
Enhancing the <javac> example, we now ha*e this:
<javac srcdir="src" debug="${build.debug}"/>
#he obvious ne$t step is to vary that property valueG to begin, let(s load properties
rom a ile.
#oading properties from a properties file
A useul method to provide coniguration and settings inormation to a build process
is to load all name5value pairs rom a properties ile that creates internal Ant properties
or each one. #o demonstrate4 we create a ile named build.properties in
the root directory o our pro"ect, where our build ile lives. #his ile has the ollowing
contents4
build.debug=off
#o load it we use one o the variants o the <property> tas!:
<property file="build.properties"/>
Croperty values in the properties ile may also contain property reerences. For e$ample,
consider a properties ile containing these lines4
build.dir=build
output.dir=${build.dir}/output
9hen loaded, output.dir will have the value build/output. Forward-reerencing
property values may be used in a single properties ile as wellG i the previous lines
had been in opposite order, the same results would be obtained. >ircular deinitions
will cause a build ailure.
NOTE Croperties that reer to relative paths are best set using the location
variant. /ee QFi$ing properties to absolute path locations.R Croperties set
rom a properties ile are set as a simple values.
/ince properties are immutable, you may want to load properties rom a ile and prei$
their name. In the last e$ample, had we used prefix="temp", the properties
created would have been temp.build.dir and temp.output.dir. #his is a nice
tric! to The absolute path of the pro0ect5s basedir (as set with the basedir
attribute of 6pro0ect7.two property iles that may have the same named property, yet ensure
that you have access to both values.
(!erriding a property
First, a little pop--ui8%e$amine the ollowing code lines and guess their output
given the properties ile "ust deined4
<target name="override">
<propert fle!"build.properties"#$
<property name="build.debug" value="on"/>
<echo message="debugging is turned %&build.debu'("/>
</target>
As you may have guessed, we would not have as!ed this -uestion had it been completely
straightorward. #he result is
[echo] debugging is turned off
A property(s value does not change once set4 properties are immutable. ,et(s e$plore
what this mechanism gives us in terms o control and le$ibility. 9hat i our properties
ile had not contained the line deining build.debug, or what i
build.properties had not e$isted8 The <property file="..."> tas! simply
does nothing but warn in verbose mode when the speciied property ile does not
e$ist. 2nly properties listed in an e$isting properties ile are loaded, so in the case
where build.debug is not present in the properties ile, its value would not be set
until it is deined in the build ile itsel, in the line <property name="build.
debug" value="on"/>.
NOTE 2nce a property has been set, either in the build ile or on the command
line, it cannot be changed. 9hoever sets a property irst i$es its value. #his
is the direct opposite o variables in a program, where the last assignment
becomes its value.
Eou have "ust witnessed the mechanism that will bring your build iles to lie4 allowing
them to adapt to user preerences, environment conditions, provide mapping
indirections, and scaling to large multi-build-ile processes.
'(%$ #here are ways to brea! the immutability o properties using OantD,
OantcallD, OavailableD, and the -D command-line option. +ost o
the reasons or these e$ceptions are logically legitimate, yet certainly an area
o conusion and concern.
#oading en!ironment !aria0les
Another important variant of <property> allows environment variables to be
pulled into Ant properties. In order to avoid inadvertent collision with e$isting Ant
properties (in other words4 what would happen i an environment variable was
named build.debug8, environment variables are loaded with a name prei$. >onsider
the ollowing e$ample4
<property environment="env"/>
All environment variables are loaded into Ant(s internal properties with the prei$
env. (including the trailing period). #his gives us properties li!e env.
CATALINA_HOME, which we can then use in tas!s related to deployment, or e$ample.
Although you can use any prei$ or environment variables, it is customary to use env.
as the prefx.
)o" the +property, tas3 is different
#he <property> tas! is special in that it has the special right to unction outside of
a <target>: it is allowed to stand alone directly as a child element o Opro"ectD.
All tas!s that appear outside o targets are evaluated beore any target is e$ecuted. 9e
recommend that you to put all such Qnontarget declarationsR o <project> beore
any target declarations, to avoid conusion.
Chec3ing for the a!aila0ility of resources6 +a!aila0le,
#he <available> tas! will set a property value i a speciied resource e$ists. It has
the capability to chec! or
W E$istence o a class in a classpath
W E$istence o a ile or directory
W E$istence o a J0+ system resource
Customi7ing Your Build Script Using Properties
In development, people oten spea! o the D:E (Don(t :epeat Eoursel) principle. #his
is a general principle aimed at ma!ing code more readable and easier to maintain by
avoiding the duplication o data. In a Java application, or e$ample, !ey values that are
used in several places, or that may need to be modiied easily, are stored as constants
or as parameters in a coniguration ile. #his ma!es the code easier to read and under-
stand, and ma!es maintenance less o a headache.
In Ant, you can do the same sort o thing by using the <property> tag, which lets you
declare constant values that can be used throughout the rest o your build ile. Declaring
a property is straightorwardG you "ust need to provide a name and value attribute, as
shown here4
Oproperty nameKL"avac.debugL valueKLonL5D
I you are reerring to a directory, you can use the location attribute instead o value4
Oproperty nameKLbuild.dirL locationKLbuildL5D
#his property value will be set to the absolute ilename o the build directory.
#o use a property elsewhere in the build ile, you "ust -uote the name o the property
surrounded by $"...#. For e$ample, you can subse-uently reer to this property anywhere
in your build ile as $"build.dir#. Eou could use the <echo> tas! to display the property
value to the screen, as shown here4
Otarget nameKLdisplay-propertiesLD
OechoDDebug K UH"avac.debugNO5echoD
OechoDSuild directory (build.dir) K UHbuild.dirNO5echoD
O5targetD
>alling this target would display the value o this property on the console. 2n my
machine, it displays the ollowing4
$ ant display-properties
Suildile4 build.$ml
display-properties4
IechoJ Suild directory (build.dir) K 5home5"ohn5pro"ects5ta$-calculator5build
S7I,D /7>>E//F7,
#otal time4 A seconds
Another way to do this would be to use the <echoproperties> tas!, which, as the name
suggests, lets you display all o the current property values to the console4
Otarget nameKLdisplay-propertiesLD
Oechoproperties 5D
O5targetD
Croperties can also be used to ta!e into account environment dierences on each de-
veloper(s machine. For e$ample, you may need to store a path to a local server or to
application directories, which may be dierent on dierent machines. #o do this, you
can store local properties in an ordinary Java properties ile. #he ollowing directories
would be dierent on 7ni$ and 9indows machines. 2n a ,inu$ development bo$,
you might have the ollowing set o properties4
chec!style.home K 5usr5local5tools5chec!style
pmd.home K 5usr5local5tools5pmd
indbugs.home K 5usr5local5tools5indbugs
cobertura.home K 5usr5local5tools5cobertura
2n a 9indows machine, by contrast, you might have something li!e this4
chec!style.home K >4<tools<chec!style
pmd.home K >4<tools<pmd
indbugs.home K >4<tools<indbugs
cobertura.home K >4<tools<cobertura
Another common use o local properties iles is to store user-speciic and5or potentially
sensitive details such as logins and passwords. #his way, this sort o data doesn(t end
up in the version control system.
Ant also comes with a set o built-in properties, such as $"basedir#, which is the absolute
path o the pro"ect base directory, as well as Java system properties li!e $"java.home#,
$"java.version#, and $"user.home#. Eou can also deine other properties based on these
properties. #his can limit the need to put a lot o variables in local properties iles. For
e$ample, suppose you want to use the FindSugs (see >hapter 36) library in your build
process. Eou could deine a deault FindSugs installation directory as a subdirectory
o the user(s home directory4
Oproperty nameKLindbugs.homeL valueKLUHuser.homeN5.indbugsL5D
7sing this deinition, any user who has installed FindSugs into this directory would
not need to conigure their local properties ile%the deault property value would
suice.
2ne nice eature here is that you can also use properties that you deine in a properties
ile to deine other properties, as shown below4
test.server K "upiter.mycompany.com
test.server.port K YAYA
test.server.url K http455UHtest.serverN4UHtest.server.portN
test.server.manager.url K UHtest.server.urlN5manager
All team members need to be aware o where these properties should be deined. #his
is important, because by deinition this is not something you can place under version
control. 2ne good approach is to agree on a properties ile naming convention (say,
use a ile called local.properties in the pro"ect home directory) and to place a docu-
mented sample ile under version control (called, or e$ample, sample.local.proper
ties). Another, possibly complementary, convention is to use a global properties ile,
stored in the user(s home directory, which contains properties that are shared between
several pro"ects. #his ile is oten called Qant-global.propertiesR or Q.ant-global.prop
erties.R
Eou can incorporate these properties into your build script by using the file attribute
in the <property> tag4
<property file$%$"user.home#!ant-global.properties%!>
<property file$%$"basedir#!local.properties%!>
OechoDchec!style.home K UHchec!style.homeNO5echoD
OechoDpmd.home K UHpmd.homeNO5echoD
OechoDindbugs.home K UHindbugs.homeNO5echoD
OechoDcobertura.home K UHcobertura.homeNO5echoD
9hen you run this, the property values will be loaded and integrated into the build ile4
$ ant compile
Suildile4 build.$ml
IechoJ chec!style.home K 5usr5local5tools5chec!style
IechoJ pmd.home K 5usr5local5tools5pmd
IechoJ indbugs.home K 5usr5local5tools5indbugs
IechoJ cobertura.home K 5usr5local5tools5cobertura
...
Eou can ma!e your build ile more robust by setting up sensible deault values or locally
deined properties. 2ne very powerul eature o Ant properties (which has caused a
lot o conusion among ine$perienced Ant users) is immutability. 2nce deined, Ant
properties cannot be modiied or the duration o the build, no matter how many
<property> tags reer to them aterward. In other words, the irst declaration o any
property wins.
,et(s loo! at a practical e$ample. /uppose you deine a property called
$"javac.debug# to indicate i you want to include debug inormation in your compiled
classes. Eou could do this as ollows4
Oproperty nameKL"avac.debugL valueKLoL5D
...
Otarget nameKLcompileL dependsKLinitL descriptionKL>ompile Java codeLD
Oecho messageKLDebug4 UH"avac.debugNL 5D
O"avac srcdirKLUHsrc.dirNL
destdirKLUHbuild.classes.dirNL
classpathreKLcompile.classpathL
debugKLUH"avac.debugNL5D
O5targetD
9hen you run this, unsurprisingly, the $"javac.debug# property is set to QoR4
$ ant compile
Suildile4 build.$ml
...
compile4
IechoJ Debug4 o
S7I,D /7>>E//F7,
#otal time4 A seconds
?ow suppose you write a ile called local.properties that you store in your pro"ect
directory. #his properties ile contains your own personal preerences or build options
such as debugging. In it, you stipulate that debugging should be on4
"avac.debug K on
And now we incorporate this properties ile into our build ile (note that we include
the properties ile before the property declaration)4
<property file$%$"basedir#!local.properties%!>
Oproperty nameKL"avac.debugL valueKLoL5D
O"avac srcdirKLsrcL destdirKLbuild5classesL debugKLUH"avac.debugNL 5D
9hen you run the build again, the irst declaration o $"javac.debug# (in the properties
ile) is considered deinitive, and the second (in the build ile) is ignored4
$ ant compile
Suildile4 build.$ml
...
compile4
IechoJ Debug4 on
S7I,D /7>>E//F7,
#otal time4 A seconds
#he story doesn(t end there, however. Eou can override any property value rom the
command line, using the -D command-line option. For e$ample, here we override the
$"javac.debug# property value to Qo.R #his will ta!e precedence over all other property
declarations4
$ ant -Djavac.debug$off compile
Suildile4 build.$ml
init4
compile4
IechoJ Debug4 o
S7I,D /7>>E//F7,
#otal time4 A seconds
8enerating Documentation "ith a!adoc
#echnical documentation is an important part o any pro"ect, and Javadoc is one o the
cornerstones o technical documentation in Java. Javadoc produces a -uite decent,
usable set o ACI documentation or your Java code, which can be a valuable aid as a
communication tool, helping team members understand what other team members are
doing. 2 course, good Javadoc re-uires well-written and meaningul comments within
the source code, and enorcing that is a tall order or any tool. And Javadoc documen-
tation is by deinition low-level reerence material%it can be very useul or an
application developer amiliar with the application, but it will be o limited use or a
new developer trying to learn the application architecture. Despite these reservations,
Javadoc should be an integral part o any development pro"ect.
It is a good idea to generate Javadoc as part o your build process. Javadoc documen-
tation should be generated and published alongside the compiled source code and the
unit test results as part o the automatic build liecycle. In Ant, you can do this using
the <javadoc> tas!. #his tas! has a lot o attributes and nested elements, but only a
ew are essential. &ere is a simple e$ample4
Otarget nameKL"avadocL dependsKLcompile,initL descriptionKL'enerate JavaDocs.LD
O"avadoc sourcepathKLUHsrc.dirNL
destdirKLUHreports."avadocNL
authorKLtrueL
versionKLtrueL
useKLtrueL
accessKLprivateL
lin!sourceKLtrueL
windowtitleKLUHant.pro"ect.nameN ACILD
OclasspathD
Opath reidKLcompile.classpathL 5D
Opathelement pathKLUHbuild.classes.dirNL 5D
O5classpathD
OdoctitleDOZI>DA#AIOh@DUHant.pro"ect.nameNO5h@DJJDO5doctitleD
ObottomDOZI>DA#AIOiD>opyright [\@T]G 3AA; All :ights :eserved.
O5iDJJDO5bottomD
O5"avadocD
O5targetD
#his tas! will generate Javadoc documentation or all the classes in the UHsrc.dirN
directory. 9e needed to provide it with a classpath containing both the compiled
classes and the application dependencies. 9e did this using an embedded <class-
path> structure. 9e could also have deined this classpath elsewhere in the build ile
and reerred to it using the classpathref attribute.
+ost o the other attributes used here are airly sel-e$planatory. #he listsource attribute
causes Ant to insert lin!s in the Javadoc document to the source code in &#+, orm.
#his is similar to the +aven J*: plugin, although the ormatting is less polished. #he
access property determines what parts o the classes should be documented. &ere we
document everything, rom the private ields up. I you want a more succinct view, you
might want to limit the "avadoc to the protected or even to only the public ields and
methods.
#here are many other options or this tas!, ar too many, in act, to cover here. +ost
involve ine-tuning ormatting details, and aren(t particularly interesting. Eou can limit
the classes being documented by providing a list o pac!ages in the packagenames at-
tribute, although i you separate your test classes rom your application source code,
the reasons or doing so are generally more rare.
Javadoc documentation is generated in the orm o a sel-contained web site. #his
ma!es it easy to deploy to your local pro"ect web site, or to bundle up with your library,
as most open source pro"ects do.
Pac3aging Your Application
2nce you have compiled and tested your application, the ne$t step is to bundle up the
compiled code into a deliverable application or library. #his can ta!e dierent orms,
depending on your pro"ect4 you may have to prepare a JA: ile, a 9A: ile, or possibly
a XIC or #A: ile containing the e$ecutable code plus other iles such as documentation
and source code. Ant has many powerul eatures that can help you prepare your ap-
plication or delivery. In the ollowing sections, we will loo! at a ew o the more
interesting ones.
8enerating a AR File
#he most undamental Java pac!aging mechanism is the JA: ile. A JA: ile is essen-
tially a XIC ile containing a hierarchy o compiled Java classes, plus some metadata.
9A: and EA: iles are similar, with some e$tra constraints on their internal directory
structure and content.
#he basic usage o the <jar> tas! is simple. &ere is an e$ample rom our sample ap-
plication, where we bundle the compiled classes into a JA: ile4
Oproperty nameKLpro"ect.nameL valueKLHant.pro"ect.nameNL 5D
Oproperty nameKLpro"ect.versionL valueKL@.AL 5D
...
Otarget nameKLpac!ageL dependsKLcompileL descriptionKL'enerate JA: ileLD
O"ar destileKLUHdist.dirN5UHpro"ect.nameN-UHpro"ect.versionN."arL basedirK
LUHbuild.classes.dirNL5D
O5targetD
:unning this will (surprise, surpriseZ) generate a JA: ile containing your compiled
classes4
$ ant clean package
Suildile4 build.$ml
clean4
IdeleteJ Deleting directory 5home5wa!aleo5pro"ects5"pt-sample-code5ant-demo5dist
IdeleteJ Deleting directory 5home5wa!aleo5pro"ects5"pt-sample-code5ant-demo5reports
init4
Im!dirJ >reated dir4 5home5wa!aleo5pro"ects5"pt-sample-code5ant-demo5dist
Im!dirJ >reated dir4 5home5wa!aleo5pro"ects5"pt-sample-code5ant-demo5reports5$ml
Im!dirJ >reated dir4 5home5wa!aleo5pro"ects5"pt-sample-code5ant-demo5reports5html
compile4
pac!age4
I"arJ Suilding "ar4 5home5wa!aleo5pro"ects5"pt-sample-code5ant-demo5dist5
ta$-calculator-@.A."ar
S7I,D /7>>E//F7,
#otal time4 A seconds
9e use the +aven convention or naming JA: iles here, which is to add the version
number to the end o the ilename. #his ma!es it easier to identiy ile versions at a
glance. #he pro"ect name comes rom the ant.project.name property, which is deined
in the Opro"ectD root element. 7sing a dierent property means that developers are
ree to change the name o the generated JA: ile by overriding this variable.
V
I you need to deploy iles rom several dierent directories, you can use <fileset> ele-
ments to deine which iles to include. For e$ample, i you also want to include iles
rom the src5resources directory, you could do the ollowing4
Oproperty nameKLpro"ect.nameL valueKLHant.pro"ect.nameNL 5D
Oproperty nameKLpro"ect.versionL valueKL@.AL 5D
...
Otarget nameKLpac!ageL dependsKLcompileL descriptionKL'enerate JA: ileLD
O"ar destileKLUHdist.dirN5UHpro"ect.nameN-UHpro"ect.versionN."arLD
Oileset dirKLUHbuild.classes.dirNL5D
Oileset dirKLsrc5resourcesL5D
O5"arD
O5targetD
I we have a loo! inside the JA: ile generated by this tas!, we might notice the e$tra
+E#A-I?F directory, which contains a ile called +A?IFE/#.+F. #his is where
metadata about the version o the ile is stored, along with other details such as the
product and vendor names4
U jar -tf dist!tax-calculator-&.'.jar
+E#A-I?F5
+E#A-I?F5+A?IFE/#.+F
com5
com5"avapowertools5
com5"avapowertools5antdemo5
com5"avapowertools5antdemo5domain5
com5"avapowertools5antdemo5web5
com5"avapowertools5antdemo5+ain.class
com5"avapowertools5antdemo5domain5>ustomer.class
com5"avapowertools5antdemo5domain5#a$>alculator.class
com5"avapowertools5antdemo5domain5#a$:ate.class
com5"avapowertools5antdemo5web5#a$>alculator>ontroller.clas
...
Sy deault, the +A?IFE/#.+F ile contains very little. A sample is shown here4
+aniest-0ersion4 @.A
Ant-0ersion4 Apache Ant @.;.A
>reated-Sy4 @.T.A-b@AB (/un +icrosystems Inc.)
&owever, this ile is a great place to put version and build numbers and5or timestamps.
Cutting a version number and a build number (or timestamp) into your deployed pac!-
ages is a good habit to get into%you never !now when you need to wor! out e$actly
which build has "ust been deployed into production. In Ant, you can add e$tra details
into the +A?IFE/#.+F ile using the <manifest> element in the <jar> tas!4
Otarget nameKLpac!ageL dependsKLcompileL descriptionKL'enerate JA: ileLD
OtstampD
Oormat propertyKLbuild.dateL patternKLEEEE, d ++++ yyyyL5D
Oormat propertyKLbuild.timeL patternKLhh4mm aL5D
O5tstampD
O"ar destileKLUHdist.dirN5UHpro"ect.nameN-UHpro"ect.versionN."arL
basedirKLUHbuild.classes.dirNL D
OmaniestD
Oattribute nameKLSuilt-SyL valueKLUHuser.nameNL5D
Oattribute nameKL/peciication-#itleL valueKLUHpro"ect.nameNL5D
Oattribute nameKL/peciication-0ersionL valueKLUHpro"ect.versionNL5D
Oattribute nameKL/peciication-0endorL valueKLA>+E IncorporatedL5D
Oattribute nameKLImplementation-#itleL valueKLcommonL5D
Oattribute nameKLImplementation-0ersionL valueKLUHpro"ect.versionN
- built at UHbuild.timeN on UHbuild.dateN L5D
Oattribute nameKLImplementation-0endorL valueKLA>+E IncorporatedL5D
O5maniestD
O5"arD
O5targetD
&ere we use the <tstamp> tas! to generate a timestamp corresponding to the current
time. #his tas! automatically sets three properties4 D()A*+, )()A*+, and
),DA-. #he irst two (D()A*+ and )()A*+) are set to the current date and time,
respectively, in a airly machine-riendly (but not particularly readable) ormat (e.g.,
Q3AA;AY3AR and Q3A3=,R respectively). #he ),DA- value is more readable (e.g., QAu-
gust 3A 3AA;R), but or a build date, we want something a little more precise. /o, we
use the nested <format> element to set some properties o our own. #he deployed
+A?IFE/#.+F ile will now loo! something li!e this4
+aniest-0ersion4 @.A
Ant-0ersion4 Apache Ant @.;.A
>reated-Sy4 @.T.A-b@AB (/un +icrosystems Inc.)
Suilt-Sy4 wa!aleo
/peciication-#itle4 ta$-calculator
/peciication-0ersion4 @.A
/peciication-0endor4 A>+E Incorporated
Implementation-#itle4 common
Implementation-0ersion4 @.A - built at @A43T C+ on +onday, 3A August
Implementation-0endor4 A>+E Incorporated
8enerating a 9AR File or an $AR File
9eb applications are usually distributed in the orm o a 9A: ile. 9A: iles can
(usually) be deployed to any Java web server using a very simple deployment procedure.
#he e$act procedure will vary rom one application server to another, but it is usually
something that can be done by a system administrator without a detailed understanding
o the application.
A 9A: ile is simply a JA: ile with a ew e$tra re-uirements. In particular, a 9A:
ile needs a special directory called 9ES-I?F, which contains application classes, libra-
ries, and coniguration iles. Files placed under this directory cannot be accessed
directly on the deployed web application, so this is a convenient place to put compiled
classes, libraries, coniguration iles, and J/C pages. #he basic directory structure o a
9A: ile is illustrated in the ollowing table.
A typical .A/ directory structure
Directory
5
9ES-I?F5
Description
Cublicly accessible web pages
>oniguration iles, not visible rom the web site
9ES-I?F5classes >ompiled classes
9ES-I?F5lib Application libraries
#he <ar> tas! is an e$tension o the <jar> tas! that ta!es into account the special
structure o a 9A: ile. Eou use special nested elements to deine the iles to go into
the 9ES-I?F5classes, 9ES-I?F5lib or 9ES-I?F directories.
/uppose you need to generate a 9A: ile or a J/C-based web application. #he J/C iles
are stored in a directory called web. #his directory also contains the 9ES-I?F sub-
directory, where we store the web.$ml ile and any other coniguration iles we need.
&owever, the application libraries and compiled classes will be obtained rom other
pro"ect directories.
Eou can create a 9A: ile rom this directory structure using the <ar> tas!, as shown
here4
Oproperty nameKLweb.dirL locationKLwebL 5D
Oproperty nameKLdist.dirL locationKLdistL 5D
Otarget nameKLwarL dependsKLcompileL descriptionKL'enerate 9A: ileLD
Owar destileKLUHdist.dirN5UHpro"ect.nameN-UHpro"ect.versionN.warL
web$mlKLUHweb.dirN59ES-I?F5web.$mlLD
Oileset dirKLUHweb.dirNL 5D
Oclasses dirKLUHbuild.classes.dirNL5D
Olib dirKLUHlibNLD
Oinclude nameKLV."arL 5D
O5libD
O5warD
O5targetD
#he usage o this tas! is similar to the <jar> tas! we saw previously (see Q'enerating
a JA: File,R earlier in this section), with a ew additions. #he most important conig-
uration ile in the 9ES-I?F directory is the web.$ml ile. As can be seen here, you use the
ebxml attribute to speciy the location o this ile.
As with the <jar> tas!, you can use one or more <fileset> elements to deine the iles
you want to deploy in the root directory. In addition, the <classes> element deines the
iles that will be placed in the 9ES-I?F5classes directory. And the <lib> element deines
the application libraries to be deployed in the 9ES-I?F5lib directory.
,i!e the <jar> tas!, the <ar> tas! will generate a +A?IFE/#.+F ile in the +E#A-I?F
directory. And li!e the <jar> tas!, you can use the <manifest> element to add e$tra
inormation into this ile.
For more comple$ applications, a 9A: ile will not be enough. I you are developing
an EJS-based application, you may need to deploy your application as an EA: ile. An
EA: ile, li!e a 9A: ile, is an e$tension o the JA: ile ormat. Instead o a web.$ml
ile, every EA: ile contains an application.$ml ile. #he OearD tas!, another e$tension
o the OjarD tas!, is airly easy to use. Eou simply speciy the location o your applica-
tion.$ml ile using the app$ml attribute, and then use one or more OfilesetD elements
to indicate what iles need to be bundled. For e$ample, i you wanted to deploy the
previous 9A: ile, plus a ew particular JA: iles (stored in a directory speciied by the
$"ear.lib# property), you could do the ollowing4
Otarget nameKLearL dependsKLwarL descriptionKL'enerate EA: ileLD
Oear destileKLUHdist.dirN5UHpro"ect.nameN-UHpro"ect.versionN.earL
app$mlKLsrc5metadata5application.$mlLD
Oileset ileKLUHdist.dirN5UHpro"ect.nameN-UHpro"ect.versionN.warL 5D
Oileset dirKLUHear.libNLD
Oinclude nameKLV."arL 5D
O5ilesetD
O5earD
O5targetD
Deploying Your Application
2nce you have generated a pac!aged version o your application, you will certainly
want to deploy it. For e$ample, i you are developing a web application, you may want
to deploy it to a web server on your own machine, or to a remote server or testing. 2r,
i you are developing a shared library, you may copy your latest version to a local web
server, where other users can consult the documentation and download the ACI.
Copying Files
#he simplest way to deploy an application is to copy the pac!aged ile to the target
server. 2 course, this will only wor! i the target server is hosted on the development
machine or i the target server has a shared drive that can be mapped to rom the
development5build machine, and the current user has write access to these directories.
Secause this is generally the case or a local development machine, this approach is
oten a simple, pragmatic way to deploy (and redeploy) a web application to a locally
running application server. Eou can copy a ile to another directory by using the
<copy> tas!, as shown here4
Oproperty nameKLtomcat.install.dirL locationKLUHuser.homeN5servers5tomcat
5apache-tomcat-B.B.36L 5D
Otarget nameKLlocal.deployL dependsKLwarL descriptionKLDeploy to local
#omcat instanceLD
Ocopy ileKLUHdist.dirN5UHpro"ect.nameN-UHpro"ect.versionN.warL
todirKLUHtomcat.install.dirN5webappsL 5D
O5targetD
In this e$ample, we simply deined a property pointing to a local #omcat installation,
and used the <copy> tas! to copy the generated 9A: ile to the #omcat webapps
directory, where #omcat will be able to pic! it up and deploy it automatically. +any
application servers wor! in the same way.
2 course, you may want to rename the 9A: ile on the way. #ypically, you may want
to strip o the version number when you deploy the web application so that users can
simply access the application using the pro"ect name. Eou can do this using the tofile
attribute instead o todir4
Oproperty nameKLtomcat.install.dirL locationKLUHuser.homeN5servers5tomcat
5apache-tomcat-B.B.36L 5D
Otarget nameKLlocal.deployL dependsKLwarL descriptionKLDeploy to local
#omcat instanceLD
Ocopy ileKLUHdist.dirN5UHpro"ect.nameN-UHpro"ect.versionN.warL
toileKLUHtomcat.install.dirN5webapps5UHpro"ect.nameN.warL 5D
O5targetD
As you might e$pect, you aren(t limited to copying a single ile. Eou can also use the
<copy> tas! to copy sets o iles, using the usual Ant path-li!e tags. For e$ample, you
might want to deploy the latest Javadoc to a local Apache web server. /uppose your
Apache server(s web directory is 5var5www5public1html, with a special subdirectory or
each pro"ect. #he Javadoc needs to be deployed to a directory called "avadoc directly
underneath the pro"ect directory. I you are running Ant on the same machine as the
Apache server, you could deploy your Javadoc simply using the <copy> tas!, as shown
here4
Oproperty nameKLweb.dirL locationKL5var5www5public1htmlL 5D
Otarget nameKLlocal.documentationL dependsKL"avadocL
descriptionKLDeploy documentation to local web serverLD
Ocopy todirKLUHweb.dirN5UHpro"ect.nameN5"avadocLD
Oileset dirKLUHreports."avadocL5D
O5copyD
O5targetD
#he <copy> tas! is a powerul, le$ible tool or ile manipulation, and here we only
cover its main eatures. >hec! out the Ant documentation or more details about what
it can do.
(ther Deployment %echni4ues
Ant provides many other ways to deploy your application. For e$ample, the <ftp> tas!
lets you deploy to an F#C server. And the <scp> tas! lets you deploy iles using the
widely used (/ecure >opy) />C protocol. A simple e$ample o the <scp> tas! is shown
here4
Otarget nameKLremote.deployL dependsKLwarL
descriptionKLDeploy to a remote integration server using />CLD
Oscp ileKLUHdist.dirN5UHpro"ect.nameN-UHpro"ect.versionN.warL
todirKLuser^testserver45home5integration5tomcatbase5webappsL
passwordKLpasswordL5D
O5targetD
#here are also many third-party libraries that can help you here.
Using Ant in $clipse
Ant is well-supported in virtually all modern Java IDEs, and Eclipse is no e$ception.
Eclipse allows you to create a new Eclipse pro"ect using an e$isting Ant ile, and rec-
ogni8es the structure o Ant build iles. #he 2utline view gives you a structured vision
o your build ile. In addition, you can e$ecute any target directly rom within Eclipse
using the conte$tual menu
Using Ant in 'etBeans
Ant integrates smoothly into ?etSeans. Indeed, by deault, ?etSeans uses Ant inter-
nally to organi8e your pro"ect, even i you don(t as! it to. ?etSeans automatically
recogni8es Ant build iles and displays the build ile targets. As in Eclipse, you can
e$ecute targets directly using the conte$tual menu.
Real time e&ample for 0uild.&ml - compiles the ej0 code- pac3ages to jar file and deploys to j0oss ser!er
+:&ml !ersion;<=.><:,
+?22 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 22,
+?22 Boss 0uild file 22,
+?22 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 22,
+project name;<Boss< default;<ej0jar< 0asedir;<.<,
+property en!ironment;<en!<@,
+property name;<src.dir< !alue;<AB0asedirC@src@main<@,
+property name;<src.resources< !alue;<AB0asedirC@src@resources<@,
+property name;<j0oss.home< !alue;<ABen!.B(SSD)(*$C<@,
+property name;<0uild.dir< !alue;<AB0asedirC@0uild<@,
+property name;<0uild.classes.dir< !alue;<AB0uild.dirC@classes<@,
+?22 Build classpath 22,
+path id;<classpath<,
+fileset dir;<ABj0oss.homeC@ser!er@default@li0<,
+include name;<E.jar<@,
+@fileset,
+fileset dir;<ABj0oss.homeC@ser!er@default@deploy@ej0F.deployer<,
+include name;<E.jar<@,
+@fileset,
+fileset dir;<ABj0oss.homeC@ser!er@default@deploy@j0oss2aop2jd3G>.deployer<,
+include name;<E.jar<@,
+@fileset,
+fileset dir;<ABj0oss.homeC@li0<,
+include name;<E.jar<@,
+@fileset,
+pathelement location;<AB0uild.classes.dirC<@,
+?22 So that "e can get jndi.properties for InitialConte&t and logHj.&ml file 22,
+pathelement location;<AB0asedirC@client2config<@,
+@path,
+property name;<0uild.classpath< refid;<classpath<@,
+?22 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 22,
+?22 Prepares the 0uild directory 22,
+?22 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 22,
+target name;<prepare< ,
+m3dir dir;<AB0uild.dirC<@,
+m3dir dir;<AB0uild.classes.dirC<@,
+@target,
+?22 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 22,
+?22 Compiles the source code 22,
+?22 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 22,
+target name;<compile< depends;<prepare<,
+ja!ac srcdir;<ABsrc.dirC<
destdir;<AB0uild.classes.dirC<
de0ug;<on<
deprecation;<on<
optimi7e;<off<
includes;<EE<,
+classpath refid;<classpath<@,
+@ja!ac,
+@target,
+target name;<ej0jar< depends;<compile<,
+jar jarfile;<0uild@titan.jar<,
+fileset dir;<AB0uild.classes.dirC<,
+include name;<com@it@domain@E.class<@,
+include name;<com@it@tra!elagent@E.class<@,
+@fileset,
+fileset dir;<ABsrc.resourcesC@<,
+include name;<*$%A2I'F@persistence.&ml<@,
+@fileset,
+@jar,
+copy file;<0uild@titan.jar< todir;<ABj0oss.homeC@ser!er@default@deploy<@,
+@target,
+target name;<run.client< depends;<ej0jar<,
+ja!a classname;<com.it.clients.Client< for3;<yes< dir;<.<,
+classpath refid;<classpath<@,
+@ja!a,
+@target,
+?22 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 22,
+?22 Cleans up generated stuff 22,
+?22 ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 22,
+target name;<clean.d0<,
+delete dir;<ABj0oss.homeC@ser!er@default@data@hypersonic<@,
+@target,
+target name;<clean<,
+delete dir;<AB0uild.dirC<@,
+delete file;<ABj0oss.homeC@ser!er@default@deploy@it.jar<@,
+@target,
+@project,
Setting Up a Project Using *a!en
*a!en and the De!elopment Build Process
9e loo! at the second ma"or player in the Java build tools arena4
+aven.

+aven is an increasingly popular open source build management tool or en-
terprise Java pro"ects, designed to ta!e much o the hard wor! out o the build process.
+aven uses a declarative approach, in which the pro"ect structure and contents are
described, rather then the tas!-based approach used in Ant or in traditional +a!e iles
or shell scripts. +aven also strongly promotes the use o standard directory structures
and a well-deined build liecycle. #his helps enorce company-wide development
standards and reduces the time needed to write and maintain build scripts.
+aven(s authors describe +aven as a Qpro"ect management ramewor!,R and it is in-
deed much more than "ust a simple build scripting tool. +aven(s declarative, standards-
based approach to pro"ect build management simpliies many aspects o the pro"ect
liecycle. As well as catering or compiling, building, testing, and deploying your
application with a minimum o eort, +aven oers a number o other !ey advantages4
W Cro"ect dependencies are declared and managed in a clean, transparent way, which
reduces the ris! o dependency-related errors and ma!es or better documentation.
W +aven lets you easily generate useul, high--uality, technical documentation and
reports about the current state o the pro"ect and pro"ect team members. ?ote that
we aren(t ta!ing about a good user manual, which is an altogether dierent issue,
but, rather, about technical documentation, written by developers or developers.
In many technical pro"ects, decent technical documentation is woeully inade-
-uate. It is nevertheless a vital part o modern sotware development, especially
when dislocated teams are involved.
W +aven proposes a clear standard directory layout or source code, pro"ect resources
and coniguration iles, generated output, and pro"ect documentation. #his ma!es
it easier to understand new +aven pro"ects, and also ma!es the +aven build scripts
cleaner and simpler.
W +aven integrates smoothly with source code repositories, continuous integration
servers, and issue trac!ing systems.
W #he +aven build cycle is le$ible4 it is easy to integrate additional build tas!s, using
e$isting +aven plug-ins or by writing Ant scriptlets.
All o these points ma!e +aven an invaluable tool or Java development teams
*a!en and Ant
9ithout a doubt, the most popular and most well-!nown build tool in the Java sphere
is Ant. Ant is a ine tool and a hugely successul open source pro"ect.
+illions o Java developers are amiliar with it. And, as we will see throughout the rest
o the boo!, there is hardly a Java tool in e$istence that doesn(t integrate with Ant.
&owever, when you write a lot o Ant build scripts, you ind yoursel as!ing yoursel
(and other team members) the same -uestions over and over again4 9here will the
source code goP 9hat about the unit testsP &ow do we handle dependenciesP &ow will
we bundle up the deliverable applicationP 9hat shall we call the main targetsP Indi-
vidually, Ant lets you deal with each o these tas!s with a high degree o le$ibility and
power. &owever, you still have to write the tas!s rom scratch or duplicate and modiy
an Ant script rom a previous pro"ect. And when you move to a new pro"ect or company,
you need to as! these -uestions once again to (begin to) understand the build process
in place.
+any (although not all) pro"ects do ollow airly common and well-!nown patterns. A
lot o what you need to conigure in your build process is pretty much run-o-the-mill.
It always seems a shame to redo the wor! again or each new pro"ect.
+aven can help you here. +aven ta!es a lot o the grunt wor! out o the build process,
and tries to lever the combined e$perience and best practice o a large community o
developers. Sy adhering to a certain number o conventions and best practices, +aven
lets you remove the drudgery o all the low-level tas!s in your build scripts. In the rest
o this chapter, we will see how.
Installing *a!en
In this chapter, we will go through how to install +aven 3 on various platorms. #he
basic installation process is straightorward, and is the same or all platorms. +aven
is a pure Java tool, so irst o all you need to ensure that there is a recent version o Java
(@.= or later) on your machine. #hen, download the latest distribution rom the +aven
download site and e$tract it into an appropriate directory. Finally, "ust add the bin
subdirectory to the system path.
I you are amiliar with installing Java tools, this should be enough to get you started.
In the rest o this chapter, we discuss some more detailed environment-speciic
considerations.
Installing *a!en on a Uni& *achine
9e run through how to install +aven into a 7ni$ environment.
Installing +aven in a 7ni$-based environment is a relatively simple tas!. Download
the latest version in the ormat o your choice, and e$tract it to an appropriate directory.
>onventions vary greatly rom one system to another, and rom one system adminis-
trator to another4 I generally place the maven installation in a nonuser-speciic directory
such as 5usr5local, as shown here4
\ cd 5usr5local
\ tar $v8 maven-3.A.;-bin.tar.g8
\ ls
#his will e$tract the maven installation in a directory called maven-3.A.;. For conven-
ience, on a 7ni$ system, I generally create a symbolic lin! to this directory to ma!e
upgrades easier to manage4
\ ln -s maven-3.A.; maven
\ ls -al
total @T
drw$r-$r-$ 6 root root =A]T 3AAT-AY-AT @64@Y .
drw$r-$r-$ B6 root root =A]T 3AAT-A;-3A 3@463 ..
lrw$rw$rw$ @ root root @@ 3AAT-AY-AT @64@; maven -D maven-3.A.;
drw$r-$r-$ T root root =A]T 3AAT-AY-AT @64@; maven-3.A.;
?ow "ust add the maven5bin directory to your environment path. #ypically, you will set
this up in one o your environment initiali8ation scripts (or e$ample, i you are using
Sash, you could place this coniguration in the _5.bashrc ile i you "ust need to set it
up or your account, or in 5etc5bashrc i you want to set it up or all users on this
machine). Don(t orget to ma!e sure that the JA0A1&2+E environment variable is deined
as well. &ere is a typical e$ample4
CA#&KUCA#&45usr5local5maven5bin
JA0A1&2+EK5usr5lib5"vm5"ava
e$port CA#& JA0A1&2+E
?ow chec! that it wor!s by running the maven command rom the command line4
\ mvn --version
+aven version4 3.A.;
Installing *a!en on a 9indo"s *achine
Installing +aven on a 9indows machine is also relatively straightorward, although
the application still lac!s the graphical installation pac!age amiliar to 9indows users.
First, download and un8ip the +aven distribution into an appropriate directory. +ost
9indows machines will have a graphical compression utility that you can use to e$tract
the XIC ile, although i you are stuc!, you can always use the Java "ar command-line
tool, as shown here4
>4D "ar -$ maven-3.A.=-bin.8ip
In t, +aven has been installed in the C4<tools<maven<maven-3.A.= directory,
although o course you can install it anywhere that suits your particular needs. A more
conventional choice might be something li!e >4<Crogram Files<Apache /otware
Foundation<maven-3.A.=. Secause it is a Java application, +aven also e$pects the
JA0A1&2+E environment variable to be correctly deined.
?e$t add the +aven bin directory to your CA#& user variable.Eou will
need to open a new console window to see the new path ta!en into account.
?ow, chec! that +aven is correctly installed by running mvn --version4
>4<Dmvn --version
+aven version4 3.A.=
?ow you should have a wor!ing +aven environment ready to goZ
Declarati!e Builds and the *a!en Project (0ject *odel
An Introduction to Declarati!e Build *anagement
Seore we loo! at how to create and wor! with pro"ects in +aven, we need to discuss
some o the basics. #he most undamental o these is the +aven Cro"ect 2b"ect +odel,
or C2+, which we will loo! at in this chapter. In the process, we also will cover some
important basic principles o +aven development, as well as a lot o the !ey eatures
o +aven. As many, i not most, new +aven users are already amiliar with Ant, we
will loo! at how the +aven approach diers rom the one used by Ant, and how this
can help simpliy your builds.
For Ant users, the +aven philosophy can ta!e a little getting use to. 7nli!e Ant, which
is very much tas!-oriented, +aven uses a highly declarative approach to pro"ect builds.
In Ant, or e$ample, you list the tas!s that must be perormed to compile, test, and
deliver your product. In +aven, by contrast, you describe your pro"ect and your build
process, relying on conventions and sensible deault values to do much o the grunt
wor!. #he heart o a +aven 3 pro"ect, the C2+, describes your pro"ect, its structure,
and its dependencies. It contains a detailed description o your pro"ect, including in-
ormation about versioning and coniguration management, dependencies, application
and testing resources, team members and structure, and much more. #he C2+ ta!es
the orm o an *+, ile (called pom.$ml by deault), which is placed in your pro"ect
home directory.
,et(s loo! at a practical e$ample. 2ne o the most undamental parts o any Java build
process involves compiling your Java classes. In a typical Ant build, you would use the
<javac> tas! to compile your classes. #his involves deining the di-
rectory or directories containing your Java source code, the directory into which the
compiled classes will be placed, and creating a classpath that contains any dependencies
needed to compile your classes. Seore invo!ing the compiler, you need to be sure to
create the target directory. #he corresponding Ant script might loo! something li!e this4
Opro"ect nameKL!iller-appLD
...
Oproperty nameKLsrc.dirL locationKLsrc5main5"avaL5D
Oproperty nameKLtarget.dirL locationKLtarget5classesL5D
...
Opath idKLcompile.classpathLD
Oileset dirKLlibLD
Oinclude nameKLVV5V."arL5D
O5ilesetD
O5pathD
...
Otarget nameKLinitLD
Om!dir directoryKLUHtarget.dirNL5D
O5targetD
Otarget nameKLcompileL dependsKLinitL descriptionKL>ompile the application classesLD
O"avac srcdirKLUHsrc.dirNL
destdirKLUHtarget.dirNL
classpathreKLcompile.classpathL
sourceKL@.BL
targetKL@.BL
5D
O5targetD
O5pro"ectD
#o compile your application, you would invo!e the QcompileR target4
U ant compile
In +aven, the build ile or this pro"ect would be somewhat dierent. First o all, you
would not need to declare the source and target directories.In act, the only thing that we need to
speciy is that our pro"ect code is written using Java B language eatures, or a Java B J0+.
+aven uses components called plug-ins to do most o the serious wor!. #he plug-in
that handles Java compilation is called maven-compiler-plugin. /o, to set up Java com-
pilation in our +aven script, all we need to do is to conigure this plug-in, which we
do as ollows4
Opro"ect...D
...
ObuildD
Oplug-insD
OZ-- 7sing Java B --D
OpluginD
OartiactIdDmaven-compiler-pluginO5artiactIdD
OconigurationD
OsourceD@.BO5sourceD
OtargetD@.BO5targetD
O5conigurationD
O5pluginD
O5plug-insD
O5buildD
...
O5pro"ectD
?ote that had we been using the deault javac source and target values, even this con-
iguration would not have been needed.
#he one thing that we glossed over here is the +aven e-uivalent o the lib directory.
In Ant, the libraries re-uired by a pro"ect are stored in a local pro"ect directory, oten
called lib. In the above e$ample, we deined a classpath called compile.classpath, which
included all the JA: iles in this directory.
+aven uses a totally dierent approach. In +aven, JA: iles are rarely, i ever, stored
in the pro"ect directory structure. Instead, dependencies are declared within the build
script itsel.
An e$tract rom a list o +aven dependencies is shown here4
Opro"ect...D
...
OZ-- C:2JE># DECE?DE?>IE/ --D
OdependenciesD
OZ-- &ibernate --D
OdependencyD
OgroupIdDorg.hibernateO5groupIdD
OartiactIdDhibernateO5artiactIdD
OversionD6.3.=.O5versionD
O5dependencyD
OZ-- ,og=" --D
OdependencyD
OgroupIdDlog="O5groupIdD
OartiactIdDlog="O5artiactIdD
OversionD@.3.@=O5versionD
O5dependencyD
...
O5dependenciesD
O5pro"ectD
Dependency management is a ma"or eature o +aven 3, and we loo! at it in much
more detail in Q+anaging #ransitive DependenciesQ in chA3-dependency-manage-
ment.
#he third part o our C2+ ile contains inormation that is largely irrelevant or the
tas! at hand (compiling our Java class), but will come in handy later on. At the start o
each +aven C2+ ile, you will ind a list o descriptive elements describing things li!e
the pro"ect name, version number, how it is to be pac!aged, and so on. #his is shown
here4
Opro"ect...D
OZ-- C:2JE># DE/>:IC#I2? --D
Omodel0ersionD=.A.AO5model0ersionD
OgroupIdDcom.mycompanyO5groupIdD
OartiactIdDmyappO5artiactIdD
Opac!agingD"arO5pac!agingD
OnameD.iller applicationO5nameD
OversionD@.AO5versionD
OdescriptionD+y new !iller appO5descriptionD
...
O5pro"ectD
&ere is the complete corresponding +aven build ile4
OP$ml versionKL@.AL encodingKL7#F-YLPD
Opro"ect $mlnsKLhttp455maven.apache.org5C2+5=.A.AL
$mlns4$siKLhttp455www.w6.org53AA@5*+,/chema-instanceL
$si4schema,ocationKLhttp455maven.apache.org5C2+5=.A.A http455maven.apache.org
5maven-v=1A1A.$sdLD
OZ-- C:2JE># DE/>:IC#I2? --D
Omodel0ersionD=.A.AO5model0ersionD
OgroupIdDcom.mycompanyO5groupIdD
OartiactIdDmyappO5artiactIdD
Opac!agingDwarO5pac!agingD
OnameD.iller applicationO5nameD
OversionD@.AO5versionD
OdescriptionD+y new !iller appO5descriptionD
OZ-- S7I,D >2?FI'7:A#I2? --D
ObuildD
Oplug-insD
OpluginD
OartiactIdDmaven-compiler-pluginO5artiactIdD
OconigurationD
OsourceD@.BO5sourceD
OtargetD@.BO5targetD
O5conigurationD
O5pluginD
O5plug-insD
O5buildD
OZ-- C:2JE># DECE?DE?>IE/ --D
OdependenciesD
OZ-- &ibernate --D
OdependencyD
OgroupIdDorg.hibernateO5groupIdD
OartiactIdDhibernateO5artiactIdD
OversionD6.3.=.O5versionD
O5dependencyD
OZ-- ,og=" --D
OdependencyD
OgroupIdDlog="O5groupIdD
OartiactIdDlog="O5artiactIdD
OversionD@.3.@=O5versionD
O5dependencyD
...
O5dependenciesD
O5pro"ectD
/o a +aven build ile is not necessarily any shorter than an Ant build ile or an e-uiv-
alent pro"ect. Sut the nature o the inormation it contains is very dierent. Ant users
will notice that there is no sign o any target-li!e structures, or any indication o what
goals can be run4
V
U mvn compile
In a similar manner, this same build ile can be used to run the application(s unit tests,
stored by convention in the src5test5"ava directory, by invo!ing the QtestR goal4
U mvn test
And this same build ile can be used to bundle up a JA: ile containing the compiled
classes, via the Qpac!ageR goal4
U mvn package
#here are many other goals. 9e will cover the main ones in the remainder o this
chapter, and in the other +aven-related chapters o this boo!.
#his illustrates another o +aven(s strong points4 all o these goals are standard +aven
goals and will wor! in a similar way on any +aven pro"ect.
As can be gleaned here, one o the guiding principles o +aven is to use sensible deault
values wherever possible. #his is where the +aven conventions play an important role.
+aven pro"ects are e$pected to respect a certain number o conventions, such as placing
your main source code in the src5main5"ava directory and your test code in the
src5main5test directory. #hese conventions are largely deined in a
special C2+ ile, the so-called /uper C2+, rom which every C2+ is e$tended. In
practice, this means that i you respect the standard +aven conventions, you can get
away with surprisingly little in your C2+ ile.
Project Conte&t and Artifacts
#he irst part o a C2+ ile basically introduces the pro"ect and its conte$t, including
the group and artiact IDs that uni-uely identiy this pro"ect in the +aven world, as
well as how the artiact is pac!aged ("ar, war, ear`), and the current version number.
#his is a small but crucial part o the +aven C2+ ile, in which you deine many !ey
aspects o your pro"ect. A typical e$ample is shown here4
Opro"ect $mlnsKLhttp455maven.apache.org5C2+5=.A.AL
$mlns4$siKLhttp455www.w6.org53AA@5*+,/chema-instanceL
$si4schema,ocationKLhttp455maven.apache.org5C2+5=.A.A
http455maven.apache.org5maven-v=1A1A.$sdLD
Omodel0ersionD=.A.AO5model0ersionD
OgroupIdDcom.mycompany.accountingO5groupIdD
OartiactIdDaccounting-coreO5artiactIdD
Opac!agingD"arO5pac!agingD
OversionD@.@O5versionD
...
#he inormation in this section is used to identiy the pro"ect uni-uely and, in particular,
the artiact that it produces. #his is one o the hallmar!s o +aven, and it is what enables
you to deine very precisely your pro"ects dependencies. Indeed, the inormation in this section
allows +aven to derive a uni-ue path to the artiact generated by this pro"ect.
.
com5mycompany5accounting5accounting-core5@.@5accounting-core-@.@."ar
com5mycompany5accounting a groupid
accounting-core a articatId
@.@ a versionId
accounting-core a artiactId
"ar a pac!aging
,et(s loo! at how +aven does this in a little more detail.
#he <group0d> element is supposed to identiy a particular pro"ect or set o libraries
within a company or organi8ation. Sy convention, it oten corresponds to the initial
part o the Java pac!age used or the application classes (e.g., Qorg.apache.mavenR or
+aven pro"ects, Qorg.springramewor!R or the /pring libraries, and so on), although
this is not always the case. 9hen the artiact is deployed to a +aven repository, the
group0d is split out into a matching directory structure on the repository.
#he artifact0d represents the actual name o the pro"ect. #his, combined with the
group0d, should uni-uely identiy the pro"ect.
Every pro"ect also has a <version> element, which indicates the current version number.
#his number usually reers to ma"or releases (Q&ibernate 6.3.=,R Q/pring 3.A.B,R and
so on), as opposed to speciic build numbers, which are dierent or each build. Each
version has its own directory on the +aven repository, which is a subdirectory o the
pro"ect directory.
/o, in the above e$ample, the generated artiact would be stored on the +aven repo-
sitory in a directory called com5mycompany5accounting5accounting-core5@.@.
9hen it comes to inally generating a deliverable pac!age, +aven supports many di-
erent ile ormats. At the time o this writing, supported pac!age types included pom,
"ar, maven-plugin, e"b, war, ear, rar, and par. As the name suggests, you use the
<packaging> element to indicate the pac!aging type. For e$ample, in this listing, +aven
will generate a ile called accounting-core-@.@."ar. #he Q"arR e$tension comes rom the
<packaging> element. +aven saves you the hassle o !nowing e$actly what iles need
to go into the delivered pac!age and what iles were delivered. All you need to do is
provide the type and +aven will do the rest.
Finally, there is an optional element called <classifier> that can be used to distinguish
dierent distributions o the same version o a product. For e$ample, you might have
a distribution or Java @.=, and a dierent distribution or Java B. #he #est?' unit
testing library does "ust this. #he pro"ect description or the Java B version o this prod-
uct might contain something li!e this4
OgroupIdDorg.testngO5groupIdD
OartiactIdDtestngO5artiactIdD
Opac!agingD"arO5pac!agingD
OversionDB.BO5versionD
OclassiierD"d!@BO5classiierD
#his would produce a ile called testng-B.@-"d!@B."ar. #he e-uivalent version or Java
@.= would be testng-B.@-"d!@=."ar.
*anaging Dependencies
2ne o the most powerul +aven eatures is the way it handles dependencies. A typical
medium-si8e Java pro"ect can re-uire do8ens, or even hundreds, o JA: iles. 9ithout
a strict dependency management strategy, this can -uic!ly become out o control. It
can rapidly become diicult to !now e$actly what library versions a particular pro"ect
is using, and conlicting dependency re-uirements can trigger hard-to-ind errors.
+aven addresses these issues using a two-pronged approach, based on the notions o
declarative dependencies and a central repository o JA: iles.
In +aven, a pro"ect(s dependencies are declared in the pom.xml ile. #he
<dependencies> section, shown here, lets you list the libraries that your application
needs to compile, be tested, and be run. Dependencies are deined using the +aven
artiact naming schema (see QCro"ect >onte$t and Artiacts,R earlier in this section),
which allows you to precisely identiy the e$act version o each library you need. In
addition, you usually only need to list the libraries you need directly to compile your
code4 with a eature called #ransitive Dependencies +aven 3 will discover and retrieve any
additional libraries that those libraries need to wor!.
&ere is a simple e$ample o the dependencies section in a C2+ ile4
...
OdependenciesD
OdependencyD
OgroupIdDorg.hibernateO5groupIdD
OartiactIdDhibernateO5artiactIdD
OversionD6.@O5versionD
O5dependencyD
OdependencyD
OgroupIdD"unitO5groupIdD
OartiactIdD"unitO5artiactIdD
OversionD6.Y.@O5versionD
OscopeDtestO5scopeD
O5dependencyD
O5dependenciesD
...
9e are saying that our application re-uires &ibernate 6.@ (and, implicitly, all the other
libraries that this version o &ibernate re-uires). And, to run our unit tests, we need
J7nit 6.Y.@.
Customi7ing Your Build Process
Although optional, the <build> section is a !ey part o any but the simplest o C2+
iles. #his section is where you tailor your +aven pro"ect build process to your e$act
needs, deining various plug-in conigurations and setting up additional tas!s that need
to be perormed at various points in the build liecycle.
#he +aven build process is very le$ible, and it is easy to integrate new tas!s by using
plug-ins. Clug-ins are a powerul way to encapsulate build logic into reusable compo-
nents, or use in uture pro"ects. Eou may use plug-ins to generate source code rom a
9/D, ile or rom &ibernate mappings, or e$ample. +any plug-ins are available, both
rom the +aven web site and rom other third-party providers such as >odehaus.
V
Secause they are used e$tensively in the standard +aven build liecycle tas!s, you also
can use plug-ins to customi8e e$isting aspects o the +aven liecycle. A common e$-
ample o this type o coniguration, shown in the e$ample below, is to conigure the
maven-compiler-plugin, which compiles the pro"ect source code or use with Java B (by
deault, the +aven compiler generates code compatible with JD. @.6).
#he <build> section is also where resource directories are deined. Eou also can deine
resources that will be bundled into the inal pac!age produced by the pro"ect, and
resources that need to be on the classpath during unit tests. Sy deault, any iles placed
in the src5main5resources will be pac!aged into the generated pro"ect artiact. Any iles
in src5test5resources will be made available on the pro"ect classpath during unit tests.
Eou also can add additional resource directories. In the ollowing e$ample, we set up
an additional resource directory or &ibernate mapping iles. At build-time, these iles
automatically will be bundled into the resulting pro"ect artiact, along with the com-
piled classes and other resource iles.
#he ollowing listing illustrates a typical build section, illustrating these e$amples4
...
ObuildD
Oplug-insD
OpluginD
OgroupIdDorg.apache.maven.plug-insO5groupIdD
OartiactIdDmaven-compiler-pluginO5artiactIdD
OconigurationD
OsourceD@.BO5sourceD
OtargetD@.BO5targetD
O5conigurationD
O5pluginD
O5plug-insD
OresourcesD
OresourceD
OdirectoryDsrc5main5hibernateO5directoryD
O5resourceD
O5resourcesD
O5buildD
...
Setting Up Reporting
An important part o any pro"ect is internal communication. Although it is not a silver
bullet, a centrali8ed technical pro"ect web site can go a long way toward improving
visibility within the team, especially with large or geographically dispersed teams. #he
site generation unctionality in +aven 3 lets you set up a proessional--uality pro"ect
web site with little eort.
Eou use the <reporting> section to conigure options or +aven site generation. In the
absence o any reporting section, +aven will generate a simple site with inormation
about the pro"ect derived rom the inormation provided in the C2+ ile. #he
<reporting> section lets you add many other additional reports, such as "avadoc, unit
test results, >hec!style or C+D reports, and so on.
In this e$ample, we add >hec!style reporting to the generated site4
OreportingD
Oplug-insD
OpluginD
OartiactIdDmaven-chec!style-pluginO5artiactIdD
OconigurationD
Oconig,ocationDconig5company-chec!s.$mlO5conig,ocationD
Oenable:ules/ummaryDalseO5enable:ules/ummaryD
Oails2nErrorDtrueO5ails2nErrorD
O5conigurationD
O5pluginD
O5reportingD
Defining Build Profiles
#he inal ma"or section o the C2+ ile is the <profiles> section. Croiles are a useul
way to customi8e the build liecycle or dierent environments. #hey let you deine
properties that change depending on your target environment, such as database con-
nections or ilepaths. At compile time, these properties can be inserted into your pro"ect
coniguration iles. For e$ample, you may need to conigure dierent database
connections or dierent platorms. /uppose JDS> coniguration details are stored in
a ile called "dbc.properties, stored in the src5main5resources directory. In this ile,
you would use a variable e$pression in the place o the property value, as shown here4
"dbc.connection.urlKUH"dbc.connection.urlN
In this case, we will deine two proiles4 one or a development database, and one or
a test database. #he <profiles> section o the C2+ ile would loo! li!e this4
OproilesD
OZ-- Development environment --D
OproileD
OidDdevelopmentO5idD
OactivationD
OactiveSyDeaultDtrueO5activeSyDeaultD
O5activationD
OpropertiesD
OZ-- #he development database --D
O"dbc.connection.urlD"dbc4mys-l455localhost5devdbO5"dbc.connection.urlD
O5propertiesD
O5proileD
OZ-- #est environment --D
OproileD
OidDtestO5idD
OpropertiesD
OZ-- #he test database --D
O"dbc.connection.urlD"dbc4mys-l455localhost5testdbO5"dbc.connection.urlD
O5propertiesD
O5proileD
O5proilesD
Each proile has an identiier (<id>) that lets you invo!e the proile by name, and a list
o property values to be used or variable substitution (in the <properties> section). For
variable substitution to wor! correctly, +aven needs to !now which iles are li!ely to
contain variables. Eou do this by activating iltering on resource directories in the
<build> section (see Q>ustomi8ing Eour Suild Crocess,R earlier in this section). #o do
this in our case, we need to activate iltering on the resource directory entry in the build
section (see Q>ustomi8ing Eour Suild CrocessR), as shown here4
...
ObuildD
OresourcesD
OresourceD
OdirectoryDsrc5main5resourcesO5directoryD
OilteringDtrueO5ilteringD
O5resourceD
O5resourcesD
O5buildD
...
Croiles can be activated in several ways. In this case, we use the active1yDefault prop-
erty to deine the development proile as the deault proile. #hereore, running a
standard +aven compile with no proiling options will use this proile4
U mvn compile
In this case, the generated "dbc.properties ile in the target5classes directory will loo!
li!e this4
"dbc.connection.urlK"dbc4mys-l455localhost5devdb
#o activate the test proile, you need to name it e$plicitly, using the -+ command line
option as shown here4
U mvn compile -+test
?ow, the generated "dbc.properties ile, in the target5classes directory, will be conig-
ured or the test database4
"dbc.connection.urlK"dbc4mys-l455localhost5testdb
9e loo! at how to use proiles in more detail in QDeining Suild Croiles.
Understanding the *a!en I #ifecycle
Cro"ect liecycles are central to +aven 3. +ost developers are amiliar with the notion
o build phases such as compile, test, and deploy. Ant build scripts typically have targets
with names li!e these. In +aven 3, this notion is standardi8ed into a set o well-!nown
and well-deined liecycle phases Instead o invo!ing tas!s or targets,
the +aven 3 developer invo!es a liecycle phase. For e$ample, to compile the applica-
tion source code, you invo!e the QcompileR liecycle phase4
U mvn compile
/ome o the more useul +aven 3 liecycle phases are the ollowing
generate-sources
'enerates any e$tra source code needed or the application, which is generally
accomplished using the appropriate plug-ins.
compile
>ompiles the pro"ect source code.
test-compile
>ompiles the pro"ect unit tests.
test
:uns the unit tests (typically using J7nit) in the src5test directory. I any tests ail,
the build will stop. In all cases, +aven generates a set o test reports in te$t and
*+, test reports in the target5sureire-reports directory
package
Cac!ages the compiled code in its distributable ormat (JA:, 9A:, etc.).
integration-test
Crocesses and deploys the pac!age i necessary into an environment in which in-
tegration tests can be run.
install
Installs the pac!age into the local repository or use as a dependency in other
pro"ects on your local machine.
deploy
In an integration or release environment, this copies the inal pac!age to the remote
repository or sharing with other developers and pro"ects.
#he ull list is much longer than this, and can be ound on the +aven web site.
V
#hese phases illustrate the beneits o the recommended practices encouraged by
+aven 34 once a developer is amiliar with the main +aven liecycle phases, he or she
should eel at ease with the liecycle phases o any +aven pro"ect. #he liecycle phase
invo!es the plug-ins it needs to do the "ob. Invo!ing a liecycle phase automatically
invo!es any previous liecycle phases as well. Secause the liecycle phases are limited
in number, easy to understand, and well organi8ed, becoming amiliar with the liecycle
o a new +aven 3 pro"ect is easy.
7nderstanding the +aven liecycle is also important when it comes to customi8ing your
build process. 9hen you customi8e your build process, you basically attach (or Qbind,R
to use the +aven terminology) plug-ins to various phases in the pro"ect liecycle. #his
may seem more rigid than Ant, in which you basically can deine any tas!s you want
and arrange them in any order you li!e. &owever, once you are amiliar with the basic
+aven phases, customi8ing the build liecycle in this way is easier to understand and
to maintain than the relatively arbitrary se-uences o tas!s that you need to implement
in an Ant build process.
%he *a!en Directory Structure
+uch o +aven(s power comes rom the standard practices that it encourages. A de-
veloper who has previously wor!ed on a +aven pro"ect immediately will eel amiliar
with the structure and organi8ation o a new one. #ime need not be wasted reinventing
directory structures, conventions, and customi8ed Ant build scripts or each pro"ect.
Although you can override any particular directory location or your own speciic ends,
you really should respect the standard +aven 3 directory structure as much as possible,
or several reasons4
W It ma!es your C2+ ile smaller and simpler.
W It ma!es the pro"ect easier to understand and ma!es lie easier or the poor guy
who must maintain the pro"ect when you leave.
W It ma!es it easier to integrate plug-ins.
#he C2+ (pom.$ml) and two subdirectories go into the pro"ect home directory4 src or
all source code and target or generated artiacts. #he src directory has a number o
subdirectories, each o which has a clearly deined purpose4
src5main5"ava
Eour Java source code goes here (strangely enoughZ)
src5main5resources
2ther resources your application needs
src5main5ilters
:esource ilters, in the orm o properties iles, which may be used to deine vari-
ables only !nown at runtime
src5main5conig
>oniguration iles
src5main5webapp
#he web application directory or a 9A: pro"ect
src5test5"ava
/ource code or unit tests, by convention in a directory structure mirroring the one
in your main source code directory
src5test5resources
:esources to be used or unit tests, but that will not be deployed
src5test5ilters
:esources ilters to be used or unit tests, but that will not be deployed
src5site
Files used to generate the +aven pro"ect web site
Configuring *a!en to Your $n!ironment
2ne o the principal aims o +aven is to produce portable pro"ect build environments.
?evertheless, each wor! environment has its particularities, which need to be catered
or. 9e investigate some common areas where you may need to tailor
+aven to suit your particular wor! environment, such as coniguring pro$y servers,
deining enterprise repositories, or speciying usernames and passwords.
9hen it comes to deining environment-speciic coniguration details, the most im-
portant tool at your disposal is the settings.$ml ile. Each user can have his or her own
individual settings.$ml ile, which should be placed in the U&2+E5.m3 directory. #his
ile is not placed under version control, and thereore can contain details such as user-
names and passwords, which should not be shared in the source code repository.
Using a Pro&y
I you are wor!ing in a company, you may well be accessing the Internet via a pro$y.
+aven relies heavily on accessing the Internet to download the libraries that it needs
or your pro"ects and or its own purposes. #hereore, i you are behind a pro$y, you
will need to tell +aven about it. +aven stores environment-speciic parameters in a ile
called U&2+E5.m35settings.$ml. Eou will have to create this ile i it doesn(t already e$ist.
#o deine a pro$y, "ust add a <proxy> element in this ile, as ollows4
OsettingsD
Opro$iesD
Opro$yD
OactiveDtrueO5activeD
OprotocolDhttpO5protocolD
OhostDpro$y.mycompany.comO5hostD
OportDYAYAO5portD
OusernameDuserO5usernameD
OpasswordDpasswordO5passwordD
OnonCro$y&ostsDV.mycompany.comO5nonCro$y&ostsD
O5pro$yD
O5pro$iesD
O5settingsD
#he Onon+roxy2ostsD element is useul to deine servers that do not need pro$y access,
such as internal enterprise repositories.
Using a #ocal *irror
Another common use o the settings.$ml ile is to conigure mirror servers. #his typ-
ically is done to conigure an organi8ation-wide repository. +any organi8ations use a
local repository to store and share internal pac!ages and to act as a pro$y to e$ternal
repositories. #his solution is aster and more reliable than re-uiring users to go to the
Internet whenever a new dependency is re-uired.
#he ollowing e$ample shows how to conigure a +aven installation to use an Arti-
actory repository e$clusively4
OsettingsD
OmirrorsD
OmirrorD
OidDartiactoryO5idD
Omirror2DVO5mirror2D
OurlDhttp455buildserver.mycomany.org4YAYA5artiactory5repoO5urlD
OnameDArtiactoryO5nameD
O5mirrorD
O5mirrorsD
O5settingsD
Changing Your *a!en Cache #ocation
+aven stores downloaded JA: iles in a local directory on your machine, !nown as the
local repository. #his directory generally is ound at U&2+E5.m35repository. 2ver time,
this directory can get pretty big. Although this usually is not an issue, it can be in some
environments where your home directory is actually stored on a remote server and
downloaded whenever you log on to a computer. In this case, i you preer to !eep your
local repository on your machine, you can redeine the local repository directory by
using the Olocal:epositoryD tag in your U&2+E5.m35settings.$ml ile4
OsettingsD
Olocal:epositoryD>45maven5repositoryO5local:epositoryD
O5settingsD
Defining Ar0itrary $n!ironment2Specific Jaria0les
#he settings.$ml ile is also a good place to let users tailor their environment variables
i they really need to. For e$ample, you might need to speciy the directory o some
locally installed product, which may vary rom machine to machine. Eou do this by
deining a deault proile in the settings.$ml ile. Any properties deined here will
override property values in the C2+ ile. 2 course, you can get the +aven build process to do
this automatically. &owever, users who have already installed /chema/py, and may
not want to duplicate installations, can override the /chema/py-related parameters by
setting up properties in their local settings.$ml ile. In the ollowing e$ample, a user
sets the installation directory (the schemaspy.home property) to C4<tools<schemaspy,
which will override any property values deined in the main C2+ ile4
OsettingsD
...
OproilesD
OproileD
OidDdevelopmentO5idD
OactivationD
OactiveSyDeaultDtrueO5activeSyDeaultD
O5activationD
OpropertiesD
Oschemaspy.homeDC4<tools<schemaspyO5schemaspy.homeD
Oschemaspy.versionD6.@.@O5schemaspy.versionD
O5propertiesD
O5proileD
O5proilesD
O5settingsD
?ote that we still need to provide sensible deault values in the C2+ ile so that cus-
tomi8ing your environment becomes optional, not mandatory. 7sers only need to
modiy their local ile i they really want to (and, presumably, when they !now what
they are doingZ). #he best way to set up these deault values is by using the
<properties> element at the end o your C2+ ile, as shown here4
Opro"ectD
...
OpropertiesD
Oschemaspy.homeDUHuser.homeN5.schemaspyO5schemaspy.homeD
Oschemaspy.versionD6.@.@O5schemaspy.versionD
O5propertiesD
Opro"ectD
Don(t be tempted to put these deault values in a deault proile element in your C2+
ileG in this case, the proile in the C2+ ile would override the proile in your local
settings.
Dependency *anagement in *a!en I
Dependency management is one o the more powerul eatures o +aven 3. Depend-
encies are the libraries you need to compile, test, and run your application. In tools
such as Ant, these libraries typically are stored in a special directory (oten called lib),
and are maintained either by hand or as pro"ect artiacts that are stored in the source
code repository along with the source code. +aven, by contrast, uses a declarative
approach. In a +aven pro"ect, you list the libraries your application needs, including
the e$act version number o each library. 7sing this inormation, +aven will do its best
to ind, retrieve, and assemble the libraries it needs during the dierent stages in the
build liecycle. In addition, using a powerul eature called #ransitive Dependencies
(see Q+anaging #ransitive Dependencies,R later in this section), it will include not only
the libraries that you declare but also all the e$tra libraries that your declared libraries
need to wor! correctly.
9e will loo! at dierent aspects o how to handle dependencies in
+aven 3.
Declaring Dependencies
2ne o the most powerul eatures o +aven 3 is its ability to handle dependencies in
a consistent and reliable manner. In the <dependencies> section o the C2+ ile, you
declare the libraries that you need to compile, test, and run your application. Depend-
encies are retrieved rom local or remote repositories, and cached locally on your
development machine, in the U&2+E5.m35repository directory structure. I you use the
same "ar in two pro"ects, it will only be downloaded (and stored) once, which saves
time and dis! space.
In +aven, dependencies are handled declaratively. /uppose that your pro"ect needs to
use &ibernate, and that your unit tests are written in J7nit. In this case, the dependency
section in your C2+ ile might loo! something li!e the ollowing4
...
OdependenciesD
OdependencyD
OgroupIdDorg.hibernateO5groupIdD
OartiactIdDhibernateO5artiactIdD
OversionD6.@O5versionD
O5dependencyD
OdependencyD
OgroupIdD"unitO5groupIdD
OartiactIdD"unitO5artiactIdD
OversionD6.Y.@O5versionD
OscopeDtestO5scopeD
O5dependencyD
O5dependenciesD
...
Each dependency is uni-uely identiied, using a +aven-style artiact. Dependencies can reer
both to other pro"ects within your organi8ation and to publicly available libraries on the public
+aven repositories.
testng-B.@-"d!@=."ar @B-Aug-3AAT AY4BB Y@;.
testng-B.@-"d!@B."ar @B-Aug-3AAT AY4BB T;T.
9hen you declare your dependencies, +aven needs to !now e$actly which version you
need. Eou do this by providing the <classifier> element, as shown here4
OdependencyD
OgroupIdDorg.testngO5groupIdD
OartiactIdDtestngO5artiactIdD
OversionDB.@O5versionD
OclassiierD"d!@BO5classiierD
OscopeDtestO5scopeD
O5dependencyD
Dependencies declarations are not limited to precise version numbers. In act, +aven
is -uite le$ible about version numbers, and you can use a orm o interval notation to
deine ranges o permissible version numbers. Interval notation comes rom set theory,
and is one o those things you probably learned at school or university and subse-uently
orgot. &ere is a -uic! reresher. Interval notation is a le$ible and concise way o
deining ranges o values using s-uare brac!ets and parentheses to indicate boundary
values. Eou use parentheses when the boundary value is not included in the set. For
e$ample, the ollowing notation indicates a set o values greater than @ (noninclusive)
and less than = (noninclusive)4
(@,=)
Eou use s-uare brac!ets when the boundary values are included in the set. For e$ample,
the ollowing notation indicates a set o values greater than or e3ual to @ and less than
or e3ual to =4
I@,=J
Eou can combine dierent types o boundary values in the same e$pression. For e$-
ample, this is how you would represent a set o values greater than or e-ual to @, and
strictly less than =4
I@,=)
Eou can leave a value out to leave one side o the set unbounded. &ere we include all
values greater or e-ual to 34
I3,)
Eou can even deine a set made up o multiple intervals, simply by listing the intervals
in a comma-separated list. #he ollowing e$ample shows how you would deine all the
values between @ and @A inclusive, e$cept or B4
I@,B),(B,@AJ
?ow that you have mastered the theory, let(s see how it applies to dependency man-
agement. Sy using interval notation, you can give +aven more le$ibility in its de-
pendency management, which means that you spend less time chasing the latest ACI
updates. +aven will use the highest available version within the range you provide. For
e$ample, the ollowing dependency will use the latest available version o &ibernate,
but re-uires at least &ibernate 6.A4
OdependencyD
OgroupIdDorg.hibernateO5groupIdD
OartiactIdDhibernateO5artiactIdD
OversionDI6.A,)O5versionD
O5dependencyD
2r you may want to limit the versions o an ACI to a particular range. 7sing the ol-
lowing dependency, +aven will loo! or the highest version o the commons-
collections in the 3.$ series, but will e$clude any versions rom 6.A onward4
OdependencyD
OgroupIdDcommons-collectionsO5groupIdD
OartiactIdDcommons-collectionsO5artiactIdD
OversionDI3.A,6.A)O5versionD
O5dependencyD
*anaging %ransiti!e Dependencies
#ransitive Dependencies are arguably one o the most useul eatures o +aven 3. I
you have ever used a tool li!e urpmi or apt-get on a ,inu$ bo$, you will be amiliar with
the concept o #ransitive Dependencies. /imply put, i you tell +aven 3 that your
pro"ect needs a particular library, it will try to wor! out what other libraries this library
needs, and retrieve them as well.
,et(s loo! at how this wor!s with a practical e$ample. /uppose that our pro"ect uses
&ibernate 6.@. 9e might declare this dependency as ollows4
OdependencyD
OgroupIdDorg.hibernateO5groupIdD
OartiactIdDhibernateO5artiactIdD
OversionD6.@O5versionD
O5dependencyD
E$actly where +aven loo!s or dependencies will depend on how your repositories are
set up. #he deault +aven 3 repository is located at http455repo@.maven.org5maven3 (i
in doubt, this is actually deined in the /uper C2+ ile). In this case, +aven will loo!
or the &ibernate JA: ile in the ollowing directory4
http455repo@.maven.org5maven35org5hibernate5hibernate56.@5
I you loo! in this directory, you will see a list o iles similar to the ollowing4
hibernate-6.@-sources."ar @A-Jan-3AAT A;4AB @.3+
hibernate-6.@-sources."ar.mdB @A-Jan-3AAT A;4AT @=Y
hibernate-6.@-sources."ar.sha@ @A-Jan-3AAT A;4A; @BT
hibernate-6.@."ar @B-Dec-3AAB @@463 @.Y+
hibernate-6.@."ar.mdB @B-Dec-3AAB @@463 63
hibernate-6.@."ar.sha@ @B-Dec-3AAB @@463 =A
hibernate-6.@.pom 3T-Dec-3AAB AT433 6.Y.
hibernate-6.@.pom.mdB A=-Jan-3AAT A;466 @6Y
hibernate-6.@.pom.sha@ A=-Jan-3AAT A;466 @=T
maven-metadata.$ml @B-Dec-3AAB @@463 @@]
maven-metadata.$ml.mdB A]-Jul-3AAT AY4=@ @6A
maven-metadata.$ml.sha@ A]-Jul-3AAT AY4=@ @6Y
?ote that there is much more than "ust the JA: ile4 there is also a C2+ ile and (or
good measure) digest iles that let +aven veriy the consistency o the iles it downloads.
#he C2+ ile here is the C2+ ile or the &ibernate pro"ect. I your pro"ect needs to
use &ibernate, it also needs to include all the &ibernate dependencies in its distribution.
#hese secondary dependencies are listed in this C2+ ile. +aven uses the dependencies
in this C2+ to wor! out what other library it needs to retrieve.
#his is the main wea!ness o +aven #ransitive Dependency management4 it relies on
the accuracy and completeness o the C2+ iles stored on the public repository. &ow-
ever, in some cases, the dependencies in the C2+ ile may not be up-to-date, and, in
other cases, the C2+ ile may actually be "ust an empty C2+ ile with no dependencies
at allZ In these cases, you will need to supply the dependencies e$plicitly in your own
C2+ ile.
Dependency management can be a complicated beast, and sometimes you will want to
understand e$actly which libraries +aven is using and why. 2ne option is to use the
45 command-line option with any +aven command to produce (among many other
things) very detailed dependency inormation. #his option generates a lot o te$t, so it
is useul to redirect output into a te$t ile and to view the ile in a te$t editor, rather
than to wrestle with the command line4
U mvn -5 test > out.txt
#he resulting output ile will contain lines li!e the ollowing, detailing the resolved
dependencies and the corresponding dependency graphs4
IDES7'J org.hibernate4hibernate4"ar46.@.64compile (setting version to4 6.@.6
rom range4 I6.A,))
IDES7'J org.hibernate4hibernate4"ar46.@.64compile (selected or compile)
IDES7'J "ava$.transaction4"ta4"ar4@.A.@S4compile (selected or compile)
IDES7'J dom="4dom="4"ar4@.T.@4compile (selected or compile)
IDES7'J cglib4cglib4"ar43.@164compile (selected or compile)
IDES7'J asm4asm4"ar4@.B.64compile (selected or compile)
IDES7'J asm4asm-attrs4"ar4@.B.64compile (selected or compile)
IDES7'J asm4asm4"ar4@.B.64compile (selected or compile)
IDES7'J commons-collections4commons-collections4"ar43.@.@4compile (removed -
nearer ound4 3.@)
IDES7'J antlr4antlr4"ar43.;.Trc@4compile (selected or compile)
#his is a representation o the dependency tree4 you can see e$actly which library ver-
sions were re-uested, and which were retained or the inal dependency list. It also
indicates which libraries were removed because a nearer dependency was ound (loo!
at the Qcommons-collectionsR library in the above listing). #his can give useul clues i
a library is not behaving as e$pected.
#he other useul tool in understanding your pro"ect(s dependencies is the Dependency
report. #his report is generated by deault when you generate the +aven site, and placed
in the target5dependencies.html ile4
U mvn site
#his report displays lists o direct and transitive dependencies or each dependency
scope
Dependency Scope
In a real-world enterprise application, you may not need to include all the dependencies
in the deployed application. /ome JA:s are needed only or unit testing, while others
will be provided at runtime by the application server. 7sing a techni-ue called de-
pendency scoping, +aven 3 lets you use certain JA:s only when you really need them
and e$cludes them rom the classpath when you don(t. +aven provides several de-
pendency scopes.
#he deault scope is the compile scope. >ompile-scope dependencies are available in
all phases.
OdependencyD
OgroupIdDorg.hibernateO5groupIdD
OartiactIdDhibernateO5artiactIdD
OversionD6.@O5versionD
O5dependencyD
A provided dependency is used to compile the application but will not be deployed.
Eou would use this scope when you e$pect the JD. or application server to provide
the JA:. #he servlet ACIs are a good e$ample4
OdependencyD
OgroupIdD"ava$.servletO5groupIdD
OartiactIdDservlet-apiO5artiactIdD
OversionD3.=O5versionD
OscopeDprovidedO5scopeD
O5dependencyD
#he runtime dependency scope is used or dependencies that are not needed or com-
pilation, only or e$ecution, such as Java Database >onnectivity (JDS>) drivers4
OdependencyD
OgroupIdDmys-lO5groupIdD
OartiactIdDmys-l-connector-"avaO5artiactIdD
OversionD6.@.@6O5versionD
OscopeDruntimeO5scopeD
O5dependencyD
Eou use the test dependency scope or dependencies that are only needed to compile
and run tests, and that don(t need to be distributed (J7nit or #est?', or e$ample)4
OdependencyD
OgroupIdD"unitO5groupIdD
OartiactIdD"unitO5artiactIdD
OversionD6.Y.@O5versionD
OscopeDtestO5scopeD
O5dependencyD
In some special cases, you may need to use system dependencies, such as the tools.jar
ile provided with the Java /D.. For e$ample, you may need to use the /un Apt or
.(6en tools within your build process. Eou can do this using the system dependency
scope. In this case (and in this case only), you need to provide a system+ath value that
indicates the absolute path to this ile. #his is illustrated in the ollowing code e$tract4
OdependencyD
OgroupIdDcom.sunO5groupIdD
OartiactIdDtoolsO5artiactIdD
OversionD@.B.AO5versionD
OscopeDsystemO5scopeD
OsystemCathDUH"ava.homeN5lib5tools."arO5systemCathD
O5dependencyD
)andling Proprietary Dependencies
For commercial and copyright reasons, not all o the commonly used libraries are
available on the public +aven repositories. A common e$ample is the 2racle JDS>
Driver, which is available ree-o-charge on the 2racle web site,
V
but it cannot be re-
distributed via a public +aven repository. Another re-uently encountered e$ample is
the Java #ransaction ACI (J#A), which is notably re-uired by &ibernate. #he J#A
library is produced by /un, which re-uires you to agree to a license agreement beore
you are able to download the JA:.
I you need to use a proprietary library li!e these in your +aven pro"ect, you will need
to add it manually to your local repository. ,et(s see how this is done, using the 2racle
driver as an e$ample.
First, download the appropriate JA: ile rom the 2racle web site (or e$ample,
odbc@=."ar). At the time o this writing, this corresponded to the Q2racle Database
@Ag :elease 3 (@A.3.A.3) JDS> Driver.R It is important to note the e$act version, as it
is not visible rom the name o the ile. #his version number will be used to identiy the
JA: ile in our repository. #he dependency declaration would loo! something li!e this4
OdependencyD
OgroupIdDoracleO5groupIdD
OartiactIdDoracle-"dbcO5artiactIdD
OversionD@A.@.A.3.AO5versionD
OscopeDruntimeO5scopeD
O5dependencyD
#o get this to wor!, we need to copy the JA: into the correct place in our +aven
repository. #here are several ways to do this. Eou may irst want to test on your devel-
opment machine beore installing the JA: onto the organi8ation repository. Eou can
install the "ar into your local repository by using the mvn install7install-file command,
as shown here4
mvn install4install-ile -DgroupIdKoracle <
-DartiactIdKoracle-"dbc <
-Dpac!agingK"ar <
-DversionK@A.@.A.3.A <
-DgenerateComKtrue <
-DileKo"dbc@=."ar
Installing the J#A "ar is similar4 download it rom the /un siteb and use the mvn in-
stall command as ollows4
mvn install4install-ile -DgroupIdK"ava$.transaction <
-DartiactIdK"ta <
-Dpac!agingK"ar <
-DversionK@.A.@S <
-DgenerateComKtrue <
-DileK"ta-@1A1@S-classes.8ip
?ow you can test the installation, typically by running some unit tests and seeing i
+aven correctly inds the dependency.
9hen you are happy, you can either deploy the ile to using the mvn deploy7deploy-
file command, or simply copy the appropriate directory onto your company +aven
repository. 9hen this is done, this dependency can be seamlessly downloaded by all
the team members in e$actly the same way as any other new dependency.
Refactoring Your Dependencies Using Properties
In large pro"ects, even with the beneits o transitive dependency management, you will
oten end up with a lot o dependencies. /ometimes, it is useul to declare !ey version
numbers in a central place, ma!ing them easier to ind and update i necessary. 2ne
good way to do this is by using properties.
9e saw in QDeining Suild CroilesR the ways in which you can deine proile or environment-
speciic properties in a proile or in the set- tings.$ml ile. &owever, you also can declare
properties directly at the root level in your pom.$ml ile. ,i!e constants in a Java class, or Ant
properties in an Ant build script, this is a convenient way to deine reusable values in an easy-to-
maintain manner. #he actual <properties> bloc! can appear anywhere in the build ile, but you
may want to put it in an easy-to-ind place such as near the start or right at the end.
,et(s loo! at an e$ample. /uppose that we are developing a web application using J/C
and J/#,. In the ollowing listing, we use two properties, somewhat unimaginatively
named servlet-api.version and jstl.version, to identiy what version o the Java /ervlet
and J/#, ACIs we are using4
Opro"ectD
...
OpropertiesD
...
Oservlet-api.versionD3.=O5servlet-api.versionD
O"stl.versionD@.@.3O5"stl.versionD
O5propertiesD
...
O5pro"ectD
#hese properties can then be used to declare our dependencies in a more le$ible man-
ner. ?ow we can use these properties to declare our /ervlet ACI and J/#, dependencies.
?ote that this ma!es it easier to ensure that the J/#, ACI and J/#, standard taglibs
versions stay in sync4
Opro"ectD
...
OpropertiesD
...
Oservlet-api.versionD3.=O5servlet-api.versionD
O"stl.versionD@.@.3O5"stl.versionD
O5propertiesD
...
OdependenciesD
...
OdependencyD
OgroupIdD"ava$.servletO5groupIdD
OartiactIdDservlet-apiO5artiactIdD
OversionD$"servlet-api.version#O5versionD
OscopeDprovidedO5scopeD
O5dependencyD
OdependencyD
OgroupIdD"ava$.servletO5groupIdD
OartiactIdD"stlO5artiactIdD
OversionD$"jstl.version#O5versionD
O5dependencyD
OdependencyD
OgroupIdDtaglibsO5groupIdD
OartiactIdDstandardO5artiactIdD
OversionD$"jstl.version#O5versionD
O5dependencyD
...
O5dependenciesD
O5pro"ectD
#oo3ing for Dependencies "ith *!nRepository
9hen you are wor!ing with +aven, you oten need to loo! up a particular dependency
so that you can add it to your C2+ ile. It can be -uite tric!y to remember and5or hunt
down the precise group and artiact names and the latest version numbers or any but
the most well-!nown artiacts. For e$ample, do you remember the e$act group and
latest version o the &ibernate or /pring +0> librariesP
2ne useul resource that can help out here is the +vn:epository site
7sing this site, you can search the central +aven repository or artiacts by name. 9hen
you ind the version you are loo!ing or, simply copy the displayed dependency bloc!
into your C2+ ile. 9hile you(re there, you also can list the dependencies o a particular
library, view the latest updates to the repository, or browse the overall structure o the
repository.
Project Inheritance and Aggregation
+aven actively encourages you to write your pro"ects as a set o small, le$ible, modules
rather than as a monolithic bloc! o code. Dependencies are one way that you can create
well-deined relationships between a set o modules to orm an overall pro"ect. Cro"ect
inheritance is another.
Cro"ect inheritance lets you deine pro"ect-wide properties and values that will be in-
herited by all o the child pro"ects. #his is most easily understood by an e$ample.
/uppose you are writing a simple web application, which will be deployed both as a
traditional web application and as a portlet. 2ne way that you might do this is to deine
three modules4 a core module, containing the application business logic, and two user
interace modules, one or each target platorm.
,et(s see how you would implement this pro"ect structure.
Carent C2+ iles are very much li!e any other C2+ ile. #he ollowing listing shows
a very simple one4
Opro"ectD
Omodel0ersionD=.A.AO5model0ersionD
OgroupIdDcom.mycompanyO5groupIdD
OartiactIdDmyappO5artiactIdD
Opac!agingDpomO5pac!agingD
OnameD.iller applicationO5nameD
OversionD@.AO5versionD
O5pro"ectD
#he main distinguishing actor is the <packaging> element, which is declared as a C2+,
rather than the 9A: or JA: values that we have seen in previous e$amples. Indeed,
all parent C2+ iles must use the pom pac!aging type.
#hen, within each child pro"ect, you need to declare a <parent> element that reers,
suprisingly enough, to the parent C2+ ile4
Opro"ectD
OparentD
OgroupIdDcom.mycompanyO5groupIdD
OartiactIdDmyappO5artiactIdD
OversionD@.AO5versionD
O5parentD
Omodel0ersionD=.A.AO5model0ersionD
OartiactIdDdebtcalculator-coreO5artiactIdD
...
O5pro"ectD
?ote that you don(t need to deine the version or groupId o the child pro"ect%these
values are inherited rom the parent.
#he parent C2+ ile is an e$cellent place to deine pro"ect-wide properties or build
coniguration details. A typical use is to deine the Java compile options in one central
place. 9e can set the Java compiler to Java @.B. #his will be inherited by all the children
pro"ects, without any special coniguration in their C2+ iles4
Opro"ectD
Omodel0ersionD=.A.AO5model0ersionD
OgroupIdDcom.mycompanyO5groupIdD
OartiactIdDmyappO5artiactIdD
Opac!agingDpomO5pac!agingD
OnameD.iller applicationO5nameD
OversionD@.AO5versionD
OpropertiesD
O"ava-api.versionD@.BO5"ava-api.versionD
O5propertiesD
ObuildD
OpluginsD
OpluginD
OartiactIdDmaven-compiler-pluginO5artiactIdD
OconigurationD
OsourceDUH"ava-api.versionNO5sourceD
OtargetDUH"ava-api.versionNO5targetD
O5conigurationD
O5pluginD
O5pluginsD
O5buildD
O5pro"ectD
In a similar way, you can deine pro"ect-wide dependencies at this level4
Opro"ectD
Omodel0ersionD=.A.AO5model0ersionD
OgroupIdDcom.mycompanyO5groupIdD
OartiactIdDmyappO5artiactIdD
Opac!agingDpomO5pac!agingD
OnameD.iller applicationO5nameD
OversionD@.AO5versionD
OpropertiesD
O"ava-api.versionD@.BO5"ava-api.versionD
O"unit.versionD=.=O5"unit.versionD
O5propertiesD
...
OdependenciesD
OdependencyD
OgroupIdD"unitO5groupIdD
OartiactIdD"unitO5artiactIdD
OversionDUH"unit.versionNO5versionD
OscopeDtestO5scopeD
O5dependencyD
O5dependenciesD
O5pro"ectD
All the children pro"ects will now be able to use these dependencies without having to
list them among their speciic dependencies. #his is also an e$cellent way to ensure
that all o your children pro"ects use the same versions o particular ACIs.
#he parent C2+ ile is also an e$cellent place to set up reporting conigurations. #his
way, you can deine and conigure the reports that you want generated or all the chil-
dren pro"ects in one central place.
Opro"ectD
Omodel0ersionD=.A.AO5model0ersionD
OgroupIdDcom.mycompanyO5groupIdD
OartiactIdDmyappO5artiactIdD
Opac!agingDpomO5pac!agingD
OnameD.iller applicationO5nameD
OversionD@.AO5versionD
...
OreportingD
OpluginsD
OpluginD
OartiactIdDmaven-sureire-report-pluginO5artiactIdD
O5pluginD
OpluginD
OartiactIdDmaven-chec!style-pluginO5artiactIdD
O5pluginD
...
O5pluginsD
O5reportingD
O5pro"ectD
Although, at the time o this writing, multimodule reporting is still a bit dodgy, each
child pro"ect will inherit the reporting coniguration deined in the parent C2+ ile,
ma!ing these iles simpler and easier to maintain.
Eou can also deine the subpro"ects as modules. #his is !nown as aggregation, and
allows you to build all the child pro"ects in one go rom the parent directory.
Opro"ectD
...
OmodulesD
OmoduleDmyapp-coreO5moduleD
OmoduleDmyapp-warO5moduleD
OmoduleDmyapp-portletO5moduleD
O5modulesD
...
O5pro"ectD
9hen you run mvn compile rom the parent root directory, all o the child pro"ects
also would be compiled4
U mvn compile
II?F2J /canning or pro"ects...
II?F2J :eactor build order4
II?F2J .iller App
II?F2J .iller App - >ore
II?F2J .iller App - Cortlet
II?F2J .iller App - 9ebapp
II?F2J ----------------------------------------------------------------------------
II?F2J Suilding .iller App
II?F2J tas!-segment4 IcompileJ
II?F2J ----------------------------------------------------------------------------
...
II?F2J ----------------------------------------------------------------------------
II?F2J Suilding .iller App - >ore
II?F2J tas!-segment4 IcompileJ
II?F2J ----------------------------------------------------------------------------
...
II?F2J ----------------------------------------------------------------------------
II?F2J Suilding .iller App - Cortlet
II?F2J tas!-segment4 IcompileJ
II?F2J ----------------------------------------------------------------------------
...
II?F2J ----------------------------------------------------------------------------
II?F2J Suilding .iller App - 9ebapp
II?F2J tas!-segment4 IcompileJ
II?F2J ----------------------------------------------------------------------------
...
II?F2J ------------------------------------------------------------------------
II?F2J :eactor /ummary4
II?F2J ------------------------------------------------------------------------
II?F2J .iller App ............................................ /7>>E// IA.6@;sJ
II?F2J .iller App - >ore ..................................... /7>>E// I@.A@3sJ
II?F2J .iller App - Cortlet .................................. /7>>E// IA.TA3sJ
II?F2J .iller App - 9ebapp ................................... /7>>E// IA.;B6sJ
II?F2J ------------------------------------------------------------------------
II?F2J ------------------------------------------------------------------------
II?F2J S7I,D /7>>E//F7,
II?F2J ------------------------------------------------------------------------
II?F2J #otal time4 = seconds
II?F2J Finished at4 /un ?ov @Y A34B=463 '+# 3AA;
II?F2J Final +emory4 ;+5YA+
II?F2J ------------------------------------------------------------------------
Creating a Project %emplate "ith Archetypes
Even with a standardi8ed directory structure, it is tiresome to have to create a ull set
o empty directories by hand whenever you start a new +aven pro"ect. #o ma!e lie
easier, +aven 3 provides the archetype plug-in, which builds an empty +aven 3%
compatible pro"ect template, containing a standard directory structure as well as some
sample iles illustrating +aven conventions and best practices. #his is an e$cellent way
to get a basic pro"ect environment up and running -uic!ly. #he deault archetype model
will produce a JA: library pro"ect. /everal other artiact types are available or other
speciic pro"ect types, including web applications, +aven plug-ins, and others.
,et(s ta!e a -uic! tour to see what you can do with +aven Archetypes. /uppose that
we want to create an online store using +aven. Following +aven(s recommendations,
we will divide the pro"ect into several distinct modules. 2ur bac!end module will be
called /hop>oreApi4
U mvn archetype7create -Dgroup0d$com.acme.shop -Dartifact0d$(hop8oreApi
-Dpackagename$com.acme.shop
II?F2J /canning or pro"ects...
II?F2J /earching repository or plugin with prei$4 )archetype).
II?F2J ----------------------------------------------------------------------------
II?F2J Suilding +aven Deault Cro"ect
II?F2J tas!-segment4 Iarchetype4createJ (aggregator-style)
II?F2J ----------------------------------------------------------------------------
...
II?F2J Archetype created in dir4 5home5"ohn5dev5pro"ects5shop5/hop>oreApi
II?F2J ------------------------------------------------------------------------
II?F2J S7I,D /7>>E//F7,
II?F2J ------------------------------------------------------------------------
II?F2J #otal time4 3 seconds
II?F2J Finished at4 /un 2ct @B 3@4BA46Y ?XD# 3AAT
II?F2J Final +emory4 =+5Y+
II?F2J ------------------------------------------------------------------------
#his will create a complete, correctly structured, wor!ing, albeit minimalist, +aven
pro"ect, including a simple C2+ ile, a sample class, and a unit test. #he C2+ ile loo!s
li!e this4
Opro"ect $mlnsKLhttp455maven.apache.org5C2+5=.A.AL $mlns4$siK
Lhttp455www.w6.org53AA@5*+,/chema-instanceL
$si4schema,ocationKLhttp455maven.apache.org5C2+5=.A.A
http455maven.apache.org5maven-v=1A1A.$sdLD
Omodel0ersionD=.A.AO5model0ersionD
OgroupIdDcom.acme.shopO5groupIdD
OartiactIdD/hop>oreApiO5artiactIdD
Opac!agingD"arO5pac!agingD
OversionD@.A-/?AC/&2#O5versionD
OnameD/hop>oreApiO5nameD
OurlDhttp455maven.apache.orgO5urlD
OdependenciesD
OdependencyD
OgroupIdD"unitO5groupIdD
OartiactIdD"unitO5artiactIdD
OversionD6.Y.@O5versionD
OscopeDtestO5scopeD
O5dependencyD
O5dependenciesD
O5pro"ectD
#he pro"ect will be created in a subdirectory with the same name o the artiact (in this
case, Q/hop>oreApiR). #he group0d and the artiactId are used to identiy the artiact
produced by the pro"ect (see QCro"ect >onte$t and ArtiactsR). #he pack-
agename is the root pac!age or your pro"ect. +ore oten than not, the packagename
option will be the same at the group0d4 in this case, you can drop the packagename
option.
#his pro"ect is now ready to try out. /witch to this directory and build the pro"ect using
mvn package4
U ls
/hop>oreApi
U cd (hop8oreApi
U mvn package
II?F2J /canning or pro"ects...
II?F2J ----------------------------------------------------------------------------
II?F2J Suilding +aven cuic! /tart Archetype
II?F2J tas!-segment4 Ipac!ageJ
II?F2J ----------------------------------------------------------------------------
...
-------------------------------------------------------
# E / # /
-------------------------------------------------------
:unning com.acme.shop.App#est
#ests run4 @, Failures4 A, Errors4 A, /!ipped4 A, #ime elapsed4 A.A6] sec
:esults 4
#ests run4 @, Failures4 A, Errors4 A, /!ipped4 A
II?F2J I"ar4"arJ
II?F2J Suilding "ar4 5home5"ohn5dev5pro"ects5shop5/hop>oreApi5target
5/hop>oreApi-@.A-/?AC/&2#."ar
II?F2J ------------------------------------------------------------------------
II?F2J S7I,D /7>>E//F7,
II?F2J ------------------------------------------------------------------------
II?F2J #otal time4 = seconds
II?F2J Finished at4 /un 2ct @B 3@4B3433 ?XD# 3AAT
II?F2J Final +emory4 =+5@A+
II?F2J ------------------------------------------------------------------------
/o, now you have a wor!ing +aven pro"ect template, generated in "ust a ew minutesZ
#he deault Archetype template (the maven-archetype--uic!start archetype) is de-
signed to produce a JA: ile. #here are also several other archetypes that can be used
to create templates or dierent types o pro"ects. Eou can use a dierent archetype by
using the archetypeArtifact0d command-line option, as shown here4
U mvn archetype7create -Dgroup0d$com.acme.shop -Dartifact0d$(hop.eb 9
-DarchetypeArtifact0d$maven-archetype-ebapp
#his e$ample uses the maven-archetype-webapp archetype, which creates (surprisingly
enoughZ) an empty 9A: pro"ect. Following +aven(s recommendations about /epa-
ration o >oncerns, the 9A: pro"ect is e$pected to contain only dynamic web pages
(J/Cs), with the actual Java code being written in another pro"ect.
Another useul archetype is the maven-archetype-site archetype, which creates a tem-
plate or a +aven web site or an e$isting pro"ect, including a ull, multilingual (well,
bilingual) site structure with sample *Doc, AC#, and FAcs content. #his archetype is
the only one that you run on an e$isting pro"ect. Although it provides none o the source
code-based reporting eatures, such as unit test reports, chec!style reports, and so on
(which need to be conigured in the main C2+ ile), it does provide a good starting
point or manually added site content4
U mvn archetype7create -Dgroup0d$com.acme.shop -Dartifact0d$(hop8oreApi 9
-DarchetypeArtifact0d$maven-archetype-site
U mvn site
II?F2J /canning or pro"ects...
II?F2J ----------------------------------------------------------------------------
II?F2J Suilding +aven cuic! /tart Archetype
II?F2J tas!-segment4 IsiteJ
II?F2J ----------------------------------------------------------------------------
...
II?F2J 'enerate L>ontinuous IntegrationL report.
II?F2J 'enerate LDependenciesL report.
II?F2J 'enerate LIssue #rac!ingL report.
II?F2J 'enerate LCro"ect ,icenseL report.
II?F2J 'enerate L+ailing ,istsL report.
II?F2J 'enerate LCro"ect /ummaryL report.
II?F2J 'enerate L/ource :epositoryL report.
II?F2J 'enerate LCro"ect #eamL report.
II?F2J ------------------------------------------------------------------------
II?F2J S7I,D /7>>E//F7,
II?F2J ------------------------------------------------------------------------
II?F2J #otal time4 @@ seconds
II?F2J Finished at4 /un 2ct @B 334=;4A= ?XD# 3AAT
II?F2J Final +emory4 @@+53@+
II?F2J ------------------------------------------------------------------------
#here is also an increasing number o third-party archetypes available or other types
o web applications and web technology stac!s, such as /truts, /pring, J/F, &ibernate,
Ageci, and many more. A list o some o these can be ound on the >odehaus web
site.
V
+att :aible(s AppFuse pro"ectb provides a large number o archetypes that you
can use to create wor!ing application templates based on a wide range o open source
architectures and libraries, such as J/F, /pring, /pring +0>, /truts, &ibernate, and
#apestry. For e$ample, the appfuse-basic-spring archetype, shown here, will create a
very complete web application prototype based on &ibernate, /pring, and J/F4
U mvn archetype7create -Dgroup0d$com.jpt -Dartifact0d$shopfront 9
-DarchetypeArtifact0d$appfuse-basic-jsf -Darchetype6roup0d$org.appfuse.archetypes
...
II?F2J Archetype created in dir4 5home5"ohn5pro"ects5shopront
II?F2J ------------------------------------------------------------------------
II?F2J S7I,D /7>>E//F7,
II?F2J ------------------------------------------------------------------------
II?F2J #otal time4 @ minute Y seconds
II?F2J Finished at4 9ed 2ct @A 3A4=T43; '+#M@34AA 3AA;
II?F2J Final +emory4 T+5TB+
II?F2J ------------------------------------------------------------------------
#his will create a e$ecutable web application, as well as a good e$ample o a wor!ing,
detailed C2+ ile or a realSy deault. It will try to connect to a local +y/c, database
(using the QrootR user with no password). Eou can try it out by running the Jetty plug-
in, as shown here4
U cd shopfront
U mvn jetty7run
...
mvn "etty4run-war
II?F2J /canning or pro"ects...
II?F2J /earching repository or plugin with prei$4 )"etty).
II?F2J ----------------------------------------------------------------------------
II?F2J Suilding AppFuse J/F Application
II?F2J tas!-segment4 I"etty4run-warJ
II?F2J ----------------------------------------------------------------------------
...
3AA;-@A-@A 3@46A4=Y.=@A44I?F24 /tarted /elect>hannel>onnector^A.A.A.A4YAYA
II?F2J /tarted Jetty /erver
Eou can now view this application by going to http7!!localhost7:':'.
Eou also can create your own archetypes, which can be useul i you want to encourage
organi8ation-wide pro"ect conventions, or to support particular types o pro"ects that
you use oten.
Compiling Code
A !ey part o any development liecycle is compiling your source code. >ompiling your
pro"ect with +aven is easy%"ust run mvn compile4
U mvn compile
Seore compiling, +aven will chec! that all the pro"ect(s dependencies have been
downloaded, and will etch any that it doesn(t already have. It also will generate any
source code or pro"ect resources that need to be generated and instantiate any variables
in the resources and coniguration iles (see QDeining Suild CroilesR).
2ne o the nice things about +aven is that these tas!s are done automatically, as part
o the normal +aven liecycle, without needing any particular coniguration.
#o be sure that there are no stale ob"ects remaining in the target directories, you can
also call the clean plug-in, which, as the name indicates, empties the output directories
in preparation or a clean build4
U mvn clean compile
Sy deault, Java compilation in +aven 3 supports bac!ward compatibility to JD. @.6,
which means that your generated artiacts will wor! ine with pretty much any modern
version o Java. #his is a useul thing to do i you are generating JA: iles or community
use, or or multiple JD.s. &owever, i you compile your brand-new Java class ull o
generics, or e$ample, you(ll get a message li!e this4
IE::2:J S7I,D FAI,7:E
II?F2J ----------------------------------------------------------------------------
II?F2J >ompilation ailure
57sers5"smart5chapters5caching5app5hibernate>aching5src5main5"ava5com5wa!aleo5
chapters5caching5businessob"ects5>ountry."ava4I=@,@YJ generics are not supported
in -source @.6
(try -source @.B to enable generics)
public /et getAirports() H
#o get your code to compile correctly using the new Java B eatures (generics and so
orth), you need to conigure the special maven-compiler-plugin in your pom.xml ile.
#his allows you to deine the source and target parameters or the Java compiler. For
Java B, you could do the ollowing4
Opro"ect...D
...
ObuildD
OpluginsD
OpluginD
OgroupIdDorg.apache.maven.plug-insO5groupIdD
OartiactIdDmaven-compiler-pluginO5artiactIdD
OconigurationD
OsourceD@.BO5sourceD
OtargetD@.BO5targetD
O5conigurationD
O5pluginD
O5pluginsD
O5buildD
O5pro"ectD
%esting Your Code
7nit tests are an important part o any modern development methodology, and they
play a !ey role in the +aven development liecycle. Sy deault, +aven will not let you
pac!age or deploy your application unless all the unit tests succeed. +aven will
recogni8e both J7nit 6.$, J7nit = and #est?' unit tests, as long as they are placed in the src5test
directory structure.
:unning unit tests rom +aven is done using the mvn test command, as shown here4
U mvn test
II?F2J /canning or pro"ects...
.
.
.
II?F2J Isureire4testJ
II?F2J /ureire report directory4 5home5"ohn5pro"ects5"ava-power-tools5...
5target5sureire-reports
-------------------------------------------------------
# E / # /
-------------------------------------------------------
:unning com."avapowertools.ta$calculator.services.#a$>alculator#est
#ests run4 @A, Failures4 A, Errors4 A, /!ipped4 A, #ime elapsed4 A.A6T sec
:unning com."avapowertools.ta$calculator.domain.#a$:ate#est
#ests run4 6, Failures4 A, Errors4 A, /!ipped4 A, #ime elapsed4 A.AA] sec
:esults 4
#ests run4 @6, Failures4 A, Errors4 A, /!ipped4 A
+aven will compile i necessary beore running the application(s unit tests. Sy deault,
+aven e$pects unit tests to be placed in the src5test directory, and will automatically
pic! up any test classes with names that start or end with Q#estR or that end with
Q#est>ase.R
Detailed test results are produced in te$t and *+, orm in the target5sureire-reports
directory. Alternatively, you can generate the test results in &#+, orm using the
sureire reporting eature4
U mvn surefire-report7report
#he &#+, report will be generated in a ile called target5site5sureire-
report.html
Another important aspect o unit testing is #est >overage, which ma!es sure that a
high proportion o your code is actually being e$ercised by your tests. Although high
test coverage is not suicient in itsel to prove that your code is being well tested, the
opposite is probably true%poor test coverage is usually a reliable sign o poorly tested
code.
>obertura is an open source coverage tool that integrates well with
+aven. Eou can measure test coverage with >obertura without any additional conig-
uration by simply invo!ing the cobertura plug-in, as shown here4
U mvn cobertura7cobertura
II?F2J /canning or pro"ects...
II?F2J /earching repository or plugin with prei$4 )cobertura).
II?F2J ----------------------------------------------------------------------------
II?F2J Suilding #a$ >alculator
II?F2J tas!-segment4 Icobertura4coberturaJ
II?F2J ----------------------------------------------------------------------------
II?F2J Creparing cobertura4cobertura
...
:eport time4 @;Yms
II?F2J >obertura :eport generation was successul.
II?F2J ------------------------------------------------------------------------
II?F2J S7I,D /7>>E//F7,
II?F2J ------------------------------------------------------------------------
II?F2J #otal time4 @; seconds
II?F2J Finished at4 9ed ?ov 3Y A]43B4BB '+# 3AA;
II?F2J Final +emory4 T+5Y@+
II?F2J ------------------------------------------------------------------------
#his will generate a detailed &#+, coverage report, which can be ound in target5
site5cobertura5inde$.html. >obertura gives a high-level summary o
code coverage across the whole pro"ect, and lets you drill down into a pac!age to in-
dividual classes where you can see which lines o code have not been tested
.
Soth o these reports also can be easily integrated into the +aven-generated pro"ect
web site.
Actually, at the time o writing, there is one slight hitch, and this won(t wor! as shown.
In act, you need to use version 3.A or 3.3 o the >obertura plug-in. Eou do this by
overriding the standard >obertura plug-in coniguration in the <build> section o your
pom.xml ile, as shown here4
OZ-- S7I,D >2?FI'7:A#I2? --D
ObuildD
OpluginsD
...
OpluginD
OgroupIdDorg.codehaus.mo"oO5groupIdD
OartiactIdDcobertura-maven-pluginO5artiactIdD
OversionD3.3O5versionD
O5pluginD
O5pluginsD
O5buildD
During debugging, you oten want to "ust run a single test. In +aven, you can do this
using the -Dtest command-line option, speciying the name o your unit test class4
U mvn -Dtest$+roductDA,)ests test
Finally, i you need to, you can also s!ip tests entirely using the -Dmaven.test.skip
option4
U mvn -Dmaven.test.skip package
Pac3aging and Deploying Your Application
2ne o the undamental principles o +aven is that each +aven pro"ect generates one,
and only one, main artiact. #he type o artiact generated by a +aven pro"ect is deined
in the <packaging> section o the C2+ ile. #he main types o pac!aging are sel-
e$planatory4 jar, ar, and ear. A typical e$ample is shown here4
Opro"ect...D
Omodel0ersionD=.A.AO5model0ersionD
OgroupIdDcom.mycompany.accountingO5groupIdD
OartiactIdDaccounting-webappO5artiactIdD
<packaging>ar<!packaging>
OversionD@.@O5versionD
...
#he pac!aging type will determine e$actly how your pro"ect is bundled together4 com-
piled classes are placed at the root o a JA: ile and in the 9ES-I?F5classes subdirectory
in a 9A: ile, or e$ample.
#he ne$t step is to install and5or deploy your application. #he install command will
generate and deploy your pro"ect artiact to the local repository on your local machine,
where it will become available to other pro"ects on your machine4
U mvn install
#he deploy command will generate and deploy your pro"ect artiact to a remote server
via one o the supported protocols (//&3, /F#C, F#C, and e$ternal //&), or simply to
a local ilesystem4
U mvn deploy
Eour application will be deployed to the remote repository deined in the
<distribution*anagement> section in your C2+ ile. I you are deploying to a V?I*
machine, you will probably need to use one o the networ! copying protocols4 //&3,
/F#C, F#C, or e$ternal //&, as in this e$ample4
Odistribution+anagementD
OrepositoryD
OidDcompany.repositoryO5idD
OnameDEnterprise +aven :epositoryO5nameD
OurlDscp455repo.acme.com5mavenO5urlD
O5repositoryD
O5distribution+anagementD
I you are deploying to a local ilesystem, or to a 9indows shared drive, you can use
the file 7:, protocol, as shown here4
Odistribution+anagementD
OrepositoryD
OidDcompany.repositoryO5idD
OnameDEnterprise +aven :epositoryO5nameD
OurlDile4555D45maven5repoO5urlD
O5repositoryD
O5distribution+anagementD
I you need to supply a username and password when you copy to the remote repository,
you also will need to provide this inormation in your settings.$ml ile4
OsettingsD
...
OserversD
OserverD
OidDcompany.repositoryO5idD
OusernameDscottO5usernameD
OpasswordDtigerO5passwordD
O5serverD
O5serversD
O5settingsD
+aven supports a variety o distribution protocols, including F#C, DA0, and />C.
&owever, not all protocols are supported out-o-the-bo$. Eou oten will need to add
an <extension> element to the <build> section in your pom.$ml ile. #his is illustrated
here, where we add support or F#C and deploy our application to an enterprise F#C
server4
O5buildD
...
Oe$tensionsD
Oe$tensionD
OgroupIdDorg.apache.maven.wagonO5groupIdD
OartiactIdDwagon-tpO5artiactIdD
OversionD@.A-beta-3O5versionD
O5e$tensionD
O5e$tensionsD
O5buildD
...
Odistribution+anagementD
OrepositoryD
OidDtp.repositoryO5idD
OnameD:emote F#C :epositoryO5nameD
OurlDtp455www.mycompany.com5public1html5reposO5urlD
O5repositoryD
OsiteD
OidDweb siteO5idD
OurlDtp455www.mycompany.com5public1htmlO5urlD
O5siteD
O5distribution+anagementD
Deploying an Application Using Cargo
#here are also many third-party tools and libraries that can help you deploy your ap-
plication. 2ne o the most versatile is >argo.V >argo is a powerul tool that allows you
to deploy your application to a number o dierent application servers, including #om-
cat, JSoss, 'eronimo, and 9eblogic. It integrates well with both +aven and Ant. 9e
don(t have room to e$plore all o its possibilities here. In this chapter, we will "ust loo!
at how to conigure >argo to deploy a 9A: application to a running remote #omcat
server.
>argo provides a +aven plug-in that allows you to integrate >argo unctionalities
smoothly into the +aven liecycle. #he coniguration is a bit wordy, mainly as a result
o the large degree o le$ibity oered by the tool. #he ull plug-in coniguration is
shown here4
OpluginD
OgroupIdDorg.codehaus.cargoO5groupIdD
OartiactIdDcargo-maven3-pluginO5artiactIdD
Oe$ecutionsD
Oe$ecutionD
OidDveriy-deployO5idD
OphaseDpre-integration-testO5phaseD
OgoalsD
OgoalDdeployer-redeployO5goalD
O5goalsD
O5e$ecutionD
O5e$ecutionsD
OconigurationD
OcontainerD
OcontainerIdDtomcatB$O5containerIdD
OtypeDremoteO5typeD
O5containerD
OconigurationD
OtypeDruntimeO5typeD
OpropertiesD
Ocargo.tomcat.manager.urlDUHtomcat.managerNO5cargo.tomcat.manager.urlD
Ocargo.remote.usernameDUHtomcat.manager.usernameNO5cargo.remote.usernameD
Ocargo.remote.passwordDUHtomcat.manager.passwordNO5cargo.remote.passwordD
O5propertiesD
O5conigurationD
OdeployerD
OtypeDremoteO5typeD
OdeployablesD
OdeployableD
OgroupIdDn8.govt.ird.egstO5groupIdD
OartiactIdDegst-webO5artiactIdD
OtypeDwarO5typeD
Oping7:,Dhttp455UHtomcat.hostN4UHtomcat.portN5UHpro"ect.build.inal?ameN
5welcome.do
O5ping7:,D
O5deployableD
O5deployablesD
O5deployerD
O5conigurationD
O5pluginD
,et(s loo! at each section in more detail.
#he irst section simply declares the plug-in in the usual way4
OpluginD
OgroupIdDorg.codehaus.cargoO5groupIdD
OartiactIdDcargo-maven3-pluginO5artiactIdD
...
In this e$ample, we automatically deploy the pac!aged 9A: ile "ust beore the inte-
gration tests phase. #his section is optional and is designed to ma!e it easier to run
automatic integration or unctional tests against the latest version o the application.
#he deployer-redeploy goal will, as you would e$pect, redeploy the application on the
targetted #omcat server4
...
Oe$ecutionsD
Oe$ecutionD
OidDveriy-deployO5idD
OphaseDpre-integration-testO5phaseD
OgoalsD
OgoalDdeployer-redeployO5goalD
O5goalsD
O5e$ecutionD
O5e$ecutionsD
...
#he ne$t section is the <configuration> element. 9e deine the type o application
server (in this case, a remote #omcat B server), and provide some server-speciic con-
iguration details indicating how to deploy to this server. For #omcat, this consists o
the 7:, or the #omcat +anager application, as well as a valid #omcat username and
password that will give us access to this server4
...
OconigurationD
OcontainerD
OcontainerIdDtomcatB$O5containerIdD
OtypeDremoteO5typeD
O5containerD
OconigurationD
OtypeDruntimeO5typeD
OpropertiesD
Ocargo.tomcat.manager.urlDUHtomcat.managerNO5cargo.tomcat.manager.urlD
Ocargo.remote.usernameDUHtomcat.manager.usernameNO5cargo.remote.usernameD
Ocargo.remote.passwordDUHtomcat.manager.passwordNO5cargo.remote.passwordD
O5propertiesD
O5conigurationD
...
For this to wor! correctly, you need to have deined a #omcat user with the QmanagerR
role. #his is not the case by deault, so you may have to modiy your #omcat conigu-
ration manually. In a deault installation, the simplest way is to add a user to the #omcat
con5tomcat-users.$ml ile, as shown here4
OP$ml versionK)@.A) encodingK)ut-Y)PD
Otomcat-usersD
Orole rolenameKLtomcatL5D
Orole rolenameKLmanagerL5D
Ouser usernameKLtomcatL passwordKLtomcatL rolesKLtomcatL5D
Ouser usernameKLadminL passwordKLsecretL rolesKLtomcat,managerL5D
O5tomcat-usersD
#his e$ample uses a number o properties, among them are thVtomcat.manager,
tomcat.manager.username, and tomcat.manager.passord. #hese properties are typi-
cally by used both by >argo and by unctional testing tools such as /elenium (see
>hapter 3A). #hey allow you to tailor the build process to dierent environments with-
out modiying the build script itsel. &ere, the tomcat.manager property indicates the
7:, pointing to the #omcat manager application. >argo uses this application to deploy
the 9A: ile, so it needs to be installed and running on your #omcat instance.
#his 7:, is built using other more environment-speciic properties. It can be placed
at the end o the pom.$ml ile, in the <properties> element, as shown here4
Opro"ectD
...
OpropertiesD
Otomcat.managerDhttp455UHtomcat.hostN4UHtomcat.portN5managerO5tomcat.managerD
O5propertiesD
O5pro"ectD
#he other properties will vary depending on the target environment. Crobably the best
way to set this up is to use +aven proiles (see QDeining Suild CroilesR).
Croiles can be placed either in the pom.$ml ile (where they will be available to all users),
or in the settings.$ml ile (or proiles that contain sensitive inormation such as server
passwords). Eou might place the development proile directly in the pom.$ml ile or
convenience4
...
OproilesD
OZ-- ,ocal development environment --D
OproileD
OidDdevO5idD
OactivationD
OactiveSyDeaultDtrueO5activeSyDeaultD
O5activationD
OpropertiesD
Otomcat.portDYAYAO5tomcat.portD
Otomcat.serverDdevelopmentO5tomcat.serverD
Otomcat.hostDlocalhostO5tomcat.hostD
Otomcat.manager.usernameDadminO5tomcat.manager.usernameD
Otomcat.manager.passwordDO5tomcat.manager.passwordD
O5propertiesD
O5proileD
...
OproilesD
...
O5pro"ectD
A developer can then redeploy by using the cargo7redeploy goal4
U mvn package cargo7redeploy
>argo also comes with other similar goals, such as cargo7deploy and cargo7undeploy,
which can be useul on occasions.
Deploying to the integration server, by contrast, re-uires a server password that you
may not want to place under version control. In addition, you may not want developers
deploying directly to the integration server rom their own machines%they may have
to do this on the build server or through a >ontinuous Integration tool. Eou can arrange
this by deining an integration server proile in the settings.$ml ile on the machine (or
machines) that will be deploying to this server (or e$ample, on the build server)4
OsettingsD
...
OproilesD
...
OZ-- Integration environment on a remote build server --D
OproileD
OidDintegrationO5idD
OactivationD
OpropertyD
OnameDenvO5nameD
OvalueDintegrationO5valueD
O5propertyD
O5activationD
OpropertiesD
Otomcat.portD@AAA@O5tomcat.portD
Otomcat.serverDintegrationO5tomcat.serverD
Otomcat.hostDbuildserver.mycompany.comO5tomcat.hostD
Otomcat.manager.usernameDadminO5tomcat.manager.usernameD
Otomcat.manager.passwordDsecretO5tomcat.manager.passwordD
O5propertiesD
O5proileD
...
OproilesD
O5settingsD
?ow, rom these machines, you can redeploy your application onto the integration
server, as shown here4
U mvn package cargo7redeploy -Denv$integration

Вам также может понравиться