We resent that question. Sample wasn’t designed to ←work, it was
designed to show you how to use Maven.
If you really ←think
this project sucks, then keep it to yourself.
We’re ←not
interested in your pestering questions.
I want to put some code in Sample Project,
Maven: The Complete Reference
178 / 316
how do I do this?
If you want to add code to this project, just start ←putting
Java source in src/main/java.
If you want to put ←some source
code in this FAQ, use the source element:
for( int i = 0; i < 1234; i++ ) {
// do something brilliant
}
10.6
Deploying Your Project Website
Once your project’s documentation has been written and you’ve creates a site to be proud of, you will
want to deploy it to a server. To deploy your site you’ll use the Maven Site plugin which can take care of
deploying your project’s site to a remote server using a number of methods including FTP, SCP, and DAV.
To deploy the site using DAV, configure the site entry of the distributionManagement section in
the POM, like this:
Configuring Site Deployment
...
sample-project.websitedav:https://dav.sample.com/sites/sample-project
...
The url in distribution management has a leading indicator dav which tells the Maven Site plugin to
deploy the site to a URL that is able to understand WebDAV. Once you have added the distribution
Maven: The Complete Reference
179 / 316
Management section to our sample-project POM, we can try deploying the site:
$ mvn clean site-deploy
If you have a server configured properly that can understand WebDAV, Maven will deploy your project’s
web site to the remote server. If you are deploying this project to a site and server visible to the public,
you are going to want to configure your web server to access for credentials. If your web server asks for
a username and password (or other credentials, you can configure this values in your ~/.m2/settings.xml).
10.6.1
Configuring Server Authentication
To configure a username/password combination for use during the site deployment, we’ll include the
following in $HOME/.m2/settings.xml:
Storing Server Authentication in User-specific Settings
...
sample-project.websitejdcaseyb@dp@ssw0rd
...
...
The server authentication section can contain a number of authentication elements. In the event you’re
using SCP for deployment, you may wish to use public-key authentication. To do this, specify the publ
icKey and passphrase elements, instead of the password element. You may still want to configure
the username element, depending on your server’s configuration.
10.6.2
Configuring File and Directory Modes
If you are working in a large group of developers, you’ll want to make sure that your web site’s files
end up with the proper user and group permissions after they are published to the remote server. To
Maven: The Complete Reference
180 / 316
configure specific file and directory modes for use during the site deployment, include the following in
$HOME/.m2/settings.xml:
Configuring File and Directory Modes on Remote Servers
...
...
hello-world.website
...
07750664
...
The above settings will make any directories readable and writable by either the owner or members of
the owner’s primary group; the anonymous users will only have access to read and list the directory.
Similarly, the owner or members of the owner’s primary group will have access to read and write any
files, with the rest of the world restricted to read-only access.
10.7
Customizing Site Appearance
The default Maven template leaves much to be desired. If you wish to customize your project’s website
beyond simply adding content, navigational elements, and custom logos. Maven offers several mechanisms for customizing your website that offer successively deeper access to content decoration and website structure. For small, per-project tweaks, providing a custom site.css is often enough. However, if
you want your customizations to be reusable across multiple projects, or if your customizations involve
changing the XHTML that Maven generates, you should consider creating your own Maven website skin.
10.7.1
Customizing the Site CSS
The easiest way to affect the look and feel of your project’s web site is through the project’s site.css. Just
like any images or XHTML content you provide for the website, the site.css file goes in the src/site/resources directory. Maven expects this file to be in the src/site/resources/css subdirectory. With CSS it is
Maven: The Complete Reference
181 / 316
possible to change text styling properties, layout properties, and even add background images and custom
bullet graphics. For example, if we decided that to make the menu heading stand out a little more, we
might try the following style in src/site/resources/css/site.css:
#navcolumn h5 {
font-size: smaller;
border: 1px solid #aaaaaa;
background-color: #bbb;
margin-top: 7px;
margin-bottom: 2px;
padding-top: 2px;
padding-left: 2px;
color: #000;
}
When you regenerate the website, the menu headers should be framed by a gray background and separated
from the rest of the menu by some extra margin space. Using this file, any structure in the Mavengenerated website can be decorated with custom CSS. When you change site.css in a specific Maven
project, the changes will apply to that specific project. If you are interested in making changes that will
apply to more than one Maven project, you can create a custom skin for the Maven Site plugin.
Tip
There is no good reference for the structure of the default Maven site template. If you are attempting to
customize the style of your Maven project, you should use a Firefox extension like Firebug as a tool to
explore the DOM for your project’s pages.
10.7.2
Create a Custom Site Template
If the default Maven Site structure just doesn’t do it for you, you can always customize the Maven site
template. Customizing the Maven Site template gives you complete control over the ultimate output of
the Maven plugin, and it is possible to customize your project’s site template to the point where it hardly
resembles the structure of a default Maven site template.
The Site plugin uses a rendering engine called Doxia, which in turn uses a Velocity template to render
the XHTML for each page. To change the page structure that is rendered by default, we can configure
the site plugin in our POM to use a custom page template. The site template is fairly complex, and
you’ll need to have a good starting point for your customization. Start by copying the default Velocity
template from Doxia’s Subversion repository default-site.vm to src/site/site.vm. This template is written
in a templating language called Velocity. Velocity is a simple templating language which supports simple
Maven: The Complete Reference
182 / 316
macro definition and allows you to access an object’s methods and properties using simple notation. A full
introduction is beyond the scope of this book, for more information about Velocity and a full introduction
please go to the Velocity project site at http://velocity.apache.org.
The default-site.xml template is fairly involved, but the change required to customize the left-hand menu
is relatively straightforward. If you are trying to change the appearance of a menuItem, locate the
menuItem macro. It resides in a section that looks like this:
#macro ( menuItem $item )
...
#end
If you replace the macro definition with the macro definition listed below, you will injects Javascript
references into each menu item which will allow the reader to expand or collapse the menu tree without
suffering through a full page reload:
#macro ( menuItem $item $listCount )
#set ( $collapse = "none" )
#set ( $currentItemHref = $PathTool.calculateLink( $item.href,
$relativePath ) )
#set ( $currentItemHref = $currentItemHref.replaceAll( "\\", "/" ) )
#if ( $item && $item.items && $item.items.size() > 0 )
#if ( $item.collapse == false )
#set ( $collapse = "collapsed" )
#else
## By default collapsed
#set ( $collapse = "collapsed" )
#end
#set ( $display = false )
#displayTree( $display $item )
#if ( $alignedFileName == $currentItemHref || $display )
#set ( $collapse = "expanded" )
#end
#end
#end
This change adds a new parameter to the menuItem macro. For the new functionality to work, you will
need to change references to this macro, or the resulting template may produce unwanted or internally
inconsistent XHTML. To finish changing these references, make a similar replacement in the mainMenu
macro. Find this macro by looking for something similar to the following template snippet:
#macro ( mainMenu $menus )
...
#end
Replace the mainMenu macro with the following implementation:
#macro ( mainMenu $menus )
#set ( $counter = 0 )
#set ( $listCounter = 0 )
#foreach( $menu in $menus )
#if ( $menu.name )
#set ( $counter = $counter + 1 )
#end
#end
This new mainMenu macro is compatible with the new menuItem macro above, and also provides
support for a Javascript-enabled top-level menu. Clicking on a top-level menu item with children will
expand the menu and allow users to see the entire tree without waiting for a page to load.
The change to the menuItem macro introduced an expand() Javascript function. This method needs
to be added to the main XHTML template at the bottom of this template file. Find the section that looks
similar to the following:
...
...
and replace it with this:
...
#if ( $decoration.body.head )
#foreach( $item in $decoration.body.head.getChildren() )
#if ( $item.name == "script" )
$item.toUnescapedString()
Maven: The Complete Reference
185 / 316
#else
$item.toString()
#end
#end
#end
After modifying the default site template, you’ll need to configure your project’s POM to reference this
new site template. To customize the site template, you’ll need to use the templateDirectory and
template configuration properties of the Maven Site plugin.
Customizing the Page Template in a Project’s POM
...
maven-site-pluginsrc/site
site.vm
...
Now, you should be able to regenerate your project website. When you do so you may notice that the
resources and CSS for the maven site are missing. When a Maven project customizes the site template,
the Site plugin expects the project to supply all of the default images and CSS. To seed your project’s
resources, you may want to copy the resources from the default Doxia site renderer project to your own
project’s resources directory by executing the following commands:
$ svn co \
http://svn.apache.org/repos/asf/maven/doxia/doxia-sitetools/\
trunk/doxia-site-renderer
$ rm \
doxia-site-renderer/src/main/resources/org/apache/maven/\
doxia/siterenderer/resources/css/maven-theme.cs+
$ cp -rf \
doxia-site-renderer/src/main/resources/org/apache/maven/\
doxia/siterenderer/resources/* \
sample-project/src/site/resources
Maven: The Complete Reference
186 / 316
Check out the doxia-site-renderer project, remove the default maven-theme.css file and then
copy all the resources to your project’s src/site/resources directory.
When you regenerate the site, you’ll notice that a few menu items look like regular unstyled text. This is
caused by a quirky interaction between the site’s CSS and our new custom page template. It can be fixed
by modifying our site.css to restore the proper link color for these menus. Simply add this:
li.collapsed, li.expanded, a:link {
color:#36a;
}
After regenerating the site, the menu’s link color should be corrected. If you applied the new site template
to the same sample-project from this chapter, you’ll notice that the menu now consists of a tree. Clicking
on "Developer Resources" no longer takes you to the "Developer Resources" page; in stead, it expands
the sub-menu. Since you’ve turned the Developer Resources menu-item into a dynamically-folding submenu, you have lost the ability to reach the developer/index.apt page. To address this change, you should
add an Overview link to the sub-menu which references the same page:
Adding a Menu Item to a Site Descriptor
...
...
10.7.3
Reusable Website Skins
If your organization is creating many Maven project sites, you will likely want to reuse site template
and CSS customizations throughout an organization. If you want thirty projects to share the same CSS
and site template, you can use Maven’s support for skinning. Maven Site skins allow you to package up
resources and templates which can be reused by other projects in lieu of duplicating your site template
for each project which needs to be customized.
Maven: The Complete Reference
187 / 316
While you can define your own skin, you may want to consider using one of Maven’s alternate skins. You
can choose from several skins. These each provide their own layout for navigation, content, logos, and
templates:
• Maven Classic Skin - org.apache.maven.skins:maven-classic-skin:1.0
• Maven Default Skin - org.apache.maven.skins:maven-default-skin:1.0
• Maven Stylus Skin - org.apache.maven.skins:maven-stylus-skin:1.0.1
You can find an up-to-date and comprehensive listing in the Maven repository: http://repo1.maven.org/maven2/org/apache/maven/skins/.
Creating a custom skin is a simple matter of wrapping your customized maven-theme.css in a Maven
project, so that it can be referenced by groupId, artifactId, and version. It can also include
resources such as images, and a replacement website template (written in Velocity) that can generate a
completely different XHTML page structure. In most cases, custom CSS can manage the changes you
desire. To demonstrate, let’s create a designer skin for the sample-project project, starting with a custom
maven-theme.css.
Before we can start writing our custom CSS, we need to create a separate Maven project to allow the
sample-project site descriptor to reference it. First, use Maven’s archetype plugin to create a basic
project. Issue the following command from the directory above the sample-project project’s root
directory:
$ mvn archetype:create -DartifactId=sample-site-skin
-DgroupId=org.sonatype.mavenbook
This will create a project (and a directory) called sample-site-skin. Change directories to the new
sample-site-skin directory, remove all of the source code and tests, and create a directory to store
your skin’s resources:
$ cd sample-site-skin
$ rm -rf src/main/java src/test
$ mkdir src/main/resources
10.7.4
Creating a Custom Theme CSS
Next, write a custom CSS for the custom skin. A custom CSS stylesheet in a Maven site skin should be
placed in src/main/resources/css/maven-theme.css. Unlike the site.css file, which goes in the site-specific
Maven: The Complete Reference
188 / 316
source directory for a project, the maven-theme.css will be bundled in a JAR artifact in your local Maven
repository. In order for the maven-theme.css file to be included in the skin’s JAR file, it must reside in the
main project-resources directory, src/main/resources.
As with the default the default site template, you will want to start customizing your new skin’s CSS
from a good starting point. Copy the CSS file used by the default Maven skin to your project’s maventheme.css. To get a copy of this theme file, save the contents of maven-theme.css from the mavendefault-skin project to src/main/resources/css/maven-theme.css in our new skin project.
Now that we have the base theme file in place, customize it using the CSS from our old site.css file.
Replace the #navcolumn h5 CSS block with the following:
#navcolumn h5 {
font-size: smaller;
border: 1px solid #aaaaaa;
background-color: #bbb;
margin-top: 7px;
margin-bottom: 2px;
padding-top: 2px;
padding-left: 2px;
color: #000;
}
Once you’ve customized the maven-theme.css, build and install the sample-site-skin JAR artifact
to your local Maven repository by running:
$ mvn clean install
Once the installation is complete, switch back to the sample-project project directory, if you already
customized the site.css earlier in this chapter, move site.css to site.css.bak so it no longer affects the
output of the Maven Site plugin:
$ mv src/site/resources/css/site.css src/site/resources/css/site.css.bak
To use the sample-site-skin in the sample-project site, you’ll need to add a reference to the
sample-site-skin artifact in the sample-project’s site descriptor. A site references a skin in
the site descriptor using the skin element:
Configuring a Custom Site Skin in Site Descriptor
...
Maven: The Complete Reference
189 / 316
org.sonatype.mavenbooksample-site-skin
...
You can think of a Maven Site skin as a site dependency. Site skins are referenced as artifacts with a
groupId and an artifactId. Using a site skin allows you to consolidate site customizations to a single
project, and makes reusing custom CSS and site templates as easy as reusing build logic through a custom
Maven plugin.
10.8
Tips and Tricks
This section lists some useful tips and tricks you can use when creating a Maven site.
10.8.1
Inject XHTML into HEAD
To inject XHTML into the HEAD element, add a head element to the body element in your project’s Site
descriptor. The following example adds a feed link to every page in the sample-project web site.
Injecting HTML into the HEAD element
...
...
Maven: The Complete Reference
10.8.2
190 / 316
Add Links under Your Site Logo
If you are working on a project which is being developed by an organization, you may want to add links
under your project’s logo. Assume that your project is a part of the Apache Software Foundation, you
might want to add a link to the Apache Software Foundation web site right below your logo, and you might
want to add a link to a parent project as well. To add links below your site logo, just add a links element
to the body element in the Site descriptor. Each item element in the links element will be rendered as a
link in a bar directly below your project’s logo. The following example would add a link to the Apache
Software Foundation followed by a link to the Apache Maven project.
Adding Links Under Your Site Logo
...
...
...
10.8.3
Add Breadcrumbs to Your Site
If your hierarchy exists within a logical hierarchy, you may want to place a series of breadcrumbs to give
the user a sense of context and give them a way to navigate up the tree to projects which might contain the
current project as a subproject. To configure breadcrumbs, add a breadcrumbs element to the body
element in the site descriptor. Each item element will render a link, and the items in the breadcrumbs
element will be rendered in order. The breadcrumb items should be listed from highest level to lowest
level. In the following site descriptor, the Codehaus item would be seen to contain the Mojo item.
Configuring the Site’s Breadcrumbs
...
...
Maven: The Complete Reference
191 / 316
...
10.8.4
Add the Project Version
When you are documenting a project that has multiple versions, it is often very helpful to list the project’s
version number on every page. To display your project’s version on the website, simply add the version
element to your site descriptor:
Positioning the Version Information
...
...
This will position the version (in the case of the sample-project project, it will say "Version: 1.0-SNAPSHOT")
in the upper left-hand corner of the site, right next to the default "Last Published" date. Valid positions
for the project version are:
left
Left side of the bar just below the site logo
right
Right side of the bar just below the site logo
navigation-top
Top of the menu
navigation-bottom
Bottom of the menu
none
Suppress the version entirely
Maven: The Complete Reference
10.8.5
192 / 316
Modify the Publication Date Format and Location
In some cases, you may wish to reformat or reposition the "Last Published" date for your project website.
Just like the project version tip above, you can specify the position of the publication date by using one
of the following:
left
Left side of the bar just below the site logo
right
Right side of the bar just below the site logo
navigation-top
Top of the menu
navigation-bottom
Bottom of the menu
none
Suppress the publication entirely
Positioning the Publish Date
...
...
By default, the publication date will be formatted using the date format string MM/dd/yyyy. You can
change this format by using the standard notation found in the JavaDocs for SimpleDateFormat (see
JavaDoc for SimpleDateFormat for more information). To reformat the date using yyyy-MM-dd, use
the following publishDate element.
Configuring the Publish Date Format
...
...
Maven: The Complete Reference
10.8.6
193 / 316
Using Doxia Macros
In addition to its advanced document rendering features, Doxia also provides a macro engine that allows
each input format to trigger injection of dynamic content. An excellent example of this is the snippet
macro, which allows a document to pull a code snippet out of a source file that’s available via HTTP.
Using this macro, a small fragment of APT can be rendered into XHTML. The following APT code calls
out to the snippet macro. Please note that this code should be on a single continuous line, the black slash
character is inserted to denote a line break so that this code will fit on the printed page.
%{snippet|id=modello-model|url=http://svn.apache.org/repos/asf/maven/\
archetype/trunk/maven-archetype/maven-archetype-model/src/main/\
mdo/archetype.mdo}
Output of the Snippet Macro in XHTML
archetypeArchetypepackageorg.apache.maven.archetype.modelArchetypeModelDescribes the assembly layout and ←packaging.1.0.0id1.0.0trueString
...
Maven: The Complete Reference
194 / 316
Warning
Doxia macros MUST NOT be indented in APT source documents. Doing so will result in the
APT parser skipping the macro altogether.
For more information about defining snippets in your code for reference by the snippet macro, see the
Guide to the Snippet Macro on the Maven website, at http://maven.apache.org/guides/mini/guide-snippetmacro.html.
Maven: The Complete Reference
195 / 316
Chapter 11
Writing Plugins
11.1
Introduction
While this chapter covers an advanced topic, don’t let the idea of writing a Maven plugin intimidate you.
For all of the theory and complexity of this tool, the fundamental concepts are easy to understand and
the mechanics of writing a plugin are straightforward. After you read this chapter, you will have a better
grasp of what is involved in creating a Maven plugin.
11.2
Programming Maven
Most of this book has dealt with using Maven, and for a book on Maven, you haven’t seen too many code
examples dealing with Maven customization. In fact, you haven’t yet seen any. This is by design, 99 out
of 100 Maven users will never need to write a custom plugin to customize Maven; there is an abundance of
configurable plugins, and unless your project has particularly unique requirements, you will have to work
to find a reason to write a new plugin. An even smaller percentage of people who end up writing custom
plugins will ever need to crack open the source code for Maven and customize a core Maven component.
If you really need to customize the behavior of Maven, then you would write a plugin. Modifying the
core Maven code is as far out of scope for most developers as modifying the TCP/IP stack on an operating
system, it is that abstract for most Maven users.
Maven: The Complete Reference
196 / 316
On the other hand, if you are going to start writing a custom plugin, you are going to have to learn a bit
about the internals of Maven: How does it manage software components? What is a Plugin? How can I
customize the lifecycle? This section answers some of those questions, and it introduces a few concepts at
the core of Maven’s design. Learning how to write a custom Maven plugin is the gateway to customizing
Maven itself. If you were wondering how to start understanding the code behind Maven, you’ve found
the proper starting line.
11.2.1
What is Inversion of Control?
At the heart of Maven is an Inversion of Control (IoC) container named Plexus. What does it do? It
is a system for managing and relating components. While there is a canonical essay about IoC written
by Martin Fowler, the concept and term have been so heavily overloaded in the past few years it is
tough to find a good definition of the concept that isn’t a self-reference (or just a lazy reference to the
aforementioned essay). Instead of resorting to a Wikipedia quote, we’ll summarize Inversion of Control
and Dependency Injection with an analogy.
Assume that you have a series of components which need to be wired together. When you think about
components, think stereo components not software components. Imagine several stereo components
hooked up to a Playstation 3 and a Tivo that have to interface with both an Apple TV box and a 50inch flat panel LCD TV. You bring everything home from the electronics store and you purchase a series
of cables that you are going to use to connect everything to everything else. You unpack all of these
components, put them in the right place, and then get to the job of hooking up fifty thousand coaxial
cables and stereo jacks to fifty thousand digital inputs and network cables. Step back from your home
entertainment center and turn on the TV, you’ve just performed dependency injection, and you’ve just
been an inversion of control container.
So what did that have to do with anything? Your Playstation 3 and a Java Bean both provide an interface.
The Playstation 3 has two inputs: power and network, and one output to the TV. Your JavaBean has three
properties: power, network, and tvOutput. When you open the box of your Playstation 3, it didn’t
provide you with detailed pictures and instructions for how to connect it to every different kind of TV
that might be in every different kind of house. When you look at your Java Bean, it just provides a set of
properties, not an explicit recipe for creating and managing an entire system of components. In an IoC
container like Plexus, you are responsible for declaring the relationships between a set of components
which simply provide an interface of inputs and outputs. You don’t instantiate objects, Plexus does;
your application’s code isn’t responsible for managing the state of components, Plexus is. Even though
it sounds very cheesy, when you start up Maven, it is starting Plexus and managing a system of related
components just like your stereo system.
What are the advantages of using an IoC container? What is the advantage of buying discrete stereo
components? If one component breaks, you can drop in a replacement for your Playstation 3 without
having to spend $20,000 on the entire system. If you are unhappy with your TV, you can swap it out
Maven: The Complete Reference
197 / 316
without affecting your CD player. Most important to you, your stereo components cost less and are more
capable and reliable because manufacturers can build to a set of known inputs and outputs and focus on
building individual components. Inversion of Control containers and Dependency Injection encourage
Disaggregation and the emergence of standards. The software industry likes to imagine itself as the font
of all new ideas, but dependency injection and inversion of control are really just new words for the
concepts of Disaggregation and interchangeable machinery. If you really want to know about DI and IoC,
learn about the Model T, the Cotton Gin, and the emergence of a railroad standard in the late 19th century.
11.2.2
Introduction to Plexus
The most important feature of an IoC container implemented in Java is a mechanism called dependency
injection. The basic idea of IoC is that the control of creating and managing objects is removed from the
code itself and placed into the hands of an IoC framework. Using dependency injection in an application
that has been programmed to interfaces, you can create components which are not bound to specific implementations of these interfaces. Instead, you program to interfaces and then configure Plexus to connect
the appropriate implementation to the appropriate component. While your code deals with interfaces, you
can capture the dependencies between classes and components in an XML file that defines components,
implementation classes, and the relationships between your components. In other words, you can write
isolated components, then you can wire them together using an XML file that defines how the components
are wired together. In the case of Plexus, system components are defined with an XML document that is
found in META-INF/plexus/components.xml.
In a Java IoC container, there are several methods for injecting dependencies values into a component
object: constructor, setter, or field injections. Although Plexus is capable of all three dependency injection
techniques, Maven only uses two types: field and setter injection.
Constructor Injection
Constructor injection is populating an object’s values through its constructor when an instance of
the object is created. For example, if you had an object of type Person which had a constructor
Person(String name, Job job), you could pass in values for both name and the job via
this constructor.
Setter Injection
Setter injection is using the setter method of a property on a Java bean to populate object dependencies. For example, if you were working with a Person object with the properties name and
job, an IoC container which uses setter injection, would create an instance of Person using a
no-arg constructor. Once it had an instance of Person, it would proceed to call the setName()
and setJob() methods.
Field Injection
Both Constructor and Setter injection rely on a call to a public method. Using Field injection,
Maven: The Complete Reference
198 / 316
an IoC container populates a component’s dependencies by setting an object’s fields directly. For
example, if you were working with a Person object that had two fields name and job, your IoC
container would populate these dependencies by setting these fields directly (i.e. person.name
="Thomas";person.job =job;)
11.2.3
Why Plexus?
Spring does happen to be the most popular IoC container at the moment, and there’s a good argument to
be made that it has affected the Java "ecosystem" for the better forcing companies like Sun Microsystems
to yield more control to the open source community and helping to open up standards by providing a
pluggable, component-oriented "bus". But, Spring isn’t the only IoC container in open source. There are
many IoC containers (like PicoContainer).
Years and years ago, when Maven was created, Spring wasn’t a mature option. The initial team of committers on Maven were more familiar with Plexus because they invented it, so they decided to use it as
an IoC container. While it might not be as popular as the Spring Framework, it is no less capable. And,
the fact that it was created by the same person who created Maven makes it a perfect fit. After reading
this chapter you’ve have an idea of how Plexus works. If you already use an IoC container you’ll notice
similarities and differences between Plexus and the container you currently use.
Note
Just because Maven is based on Plexus doesn’t mean that the Maven community is "anti-Spring" (we’ve
included a whole chapter with a Spring example in this book, portions of the Spring project are moving
to Maven as a build platform). The question, "Why didn’t you use Spring?" comes up often enough it
did make sense to address it here. We know it, Spring is a rock star, we don’t deny it, and it is on our
continuing to-do list to introduce people to (and document) Plexus: choice in the software industry is
always a good thing.
11.2.4
What is a Plugin?
A Maven Plugin is a Maven artifact which contains a plugin descriptor and one or more Mojos. A Mojo
can be thought of as a goal in Maven, and every goal corresponds to a Mojo. The compiler:compile
goal corresponds to the CompilerMojo class in the Maven Compiler Plugin, and the jar:jar goal
corresponds to the JarMojo class in the Maven Jar Plugin. When you write your own plugin, you are
Maven: The Complete Reference
simply grouping together a set of related Mojos (or goals) in a single plugin artifact.
199 / 316
1
Note
Mojo? What is a Mojo? The word mojo is defined as "a magic charm or spell", "an amulet, often in a
small flannel bag containing one or more magic items", and "personal magnetism; charm". Maven uses
the term Mojo because it is a play on the word Pojo (Plain-old Java Object).
A Mojo is much more than just a goal in Maven, it is a component managed by Plexus that can include
references to other Plexus components.
11.3
Plugin Descriptor
A Maven plugin contains a road-map for Maven that tells Maven about the various Mojos and plugin
configuration. This plugin descriptor is present in the plugin JAR file in META-INF/maven/plugin.xml.
When Maven loads a plugin, it reads this XML file, instantiates and configures plugin objects to make the
Mojos contained in a plugin available to Maven.
When you are writing custom Maven plugins, you will almost never need to think about writing a plugin
descriptor. In Chapter 4, the lifecycle goals bound to the maven-plugin packaging type show that the
plugin:descriptor goal is bound to the generate-resources phase. This goal generates a
plugin descriptor off of the annotations present in a plugin’s source code. Later in this chapter, you will
see how Mojos are annotated, and you will also see how the values in these annotations end up in the
META-INF/maven/plugin.xml file.
Plugin Descriptor shows a plugin descriptor for the Maven Zip Plugin. This plugin is a contrived plugin
that simply zips up the output directory and produces an archive. Normally, you wouldn’t need to write a
custom plugin to create an archive from Maven, you could simply use the Maven Assembly Plugin which
is capable of producing a distribution archive in multiple formats. Read through the following plugin
descriptor to get an idea of the content it contains.
Plugin Descriptor
com.training.plugins
1 "mojo." The American Heritage® Dictionary of the English Language, Fourth Edition. Houghton Mifflin Company, 2004.
Answers.com 02 Mar. 2008
Maven: The Complete Reference
200 / 316
maven-zip-plugin1-SNAPSHOTzipfalsetruezipZips up the output directory.falsetruefalsefalsefalsetruepackagecom.training.plugins.ZipMojojavaper-lookuponce-per-sessionbaseDirectoryjava.io.FilefalsetrueBase directory of the project. ←description>
buildDirectoryjava.io.FilefalsetrueDirectory containing the build files. ←description>
${project.build.directory}
${basedir}org.codehaus.plexus.archiver.ArchiverzipzipArchiver
Maven: The Complete Reference
201 / 316
org.apache.commonscommons-io1.3.2
There are three parts to a plugin descriptor: the top-level configuration of the plugin which contains elements like groupId and artifactId, the declaration of mojos, and the declaration of dependencies.
Let’s examine each of these sections in more detail.
11.3.1
Top-level Plugin Descriptor Elements
The top-level configuration values in the plugin element are:
description
This element contains a short description of the plugin. In the case of the Zip plugin, this description
is empty.
groupId, artifactId, version
As with everything else in Maven, plugins need to have a unique set of coordinates. The groupId,
artifactId, and version are used to locate the plugin artifact in a Maven repository.
goalPrefix
This element controls the prefix used to reference goals in a particular plugin. If you were to look at
the Compiler plugin’s descriptor you would see that goalPrefix has a value of compiler. If
you look at the descriptor for the Jar plugin, it would have a goalPrefix of jar. It is important
that you choose a distinct goal prefix for your custom plugin.
isolatedRealm (deprecated)
This is a legacy property which is no longer used by Maven. It is still present in the system to
provide backwards compatibility with older plugins. Earlier versions of Maven used to provide a
mechanism to load a plugin’s dependencies in an isolated ClassLoader. Maven makes extensive
use of a project called ClassWorlds from the Codehaus community to create hierarchies of Class
Loader objects which are modeled by a ClassRealm object. Feel free to ignore this property
and always set it to false.
inheritedByDefault
If inheritedByDefault is set to true, any mojo in this plugin which is configured in a parent project
Maven: The Complete Reference
202 / 316
will be configured in a child project. If you configure a mojo to execute during a specific phase in a
parent project and the Plugin has inheritedByDefault set to true, this execution will be inherited by
the child project. If inheritedByDefault is not set to true, then an goal execution defined in a parent
project will not be inherited by a child project.
11.3.2
Mojo Configuration
Next is the declaration of each Mojo. The plugin element contains an element named mojos which
contains a mojo element for each mojo present in the Plugin. Each mojo element contains the following
configuration elements:
goal
This is the name of the goal. If you were running the compiler:compile goal, then compiler
is the plugin’s goalPrefix and compile would be the name of the goal.
description
This contains a short description of the goal to display to the user when they use the Help plugin to
generate plugin documentation.
requiresDirectInvocation
If you set this to true, the goal can only be executed if it is explicitly executed from the commandline by the user. If someone tries to bind this goal to a lifecycle phase in a POM, Maven will print an
error message. The default for this element is false.
nexus*http://localhost:8081/nexus/content/groups/publicnexuscentralhttp://centraltruetruecentralhttp://centraltruetrue
Maven: The Complete Reference
245 / 316
nexus
This XML file configures Maven to consult a single public repository group for all configured repositories
and plugin repositories. It is a simple way to guarantee that every request for an artifact is made through
your Nexus installation.
13.2.3
Configuring Environment to Support Flex Unit Tests
Flexmojos expects to be able to launch the stand-alone Flash Player to execute unit tests. In order for this
to work, you will need to add the stand-alone Flash Player to your PATH, or you will need to pass the
location of the Flash Player executable to your build using the -DflashPlayer.command options.
When executing a unit test, Flex Mojos expects to launch the following platform-specific executables for
the stand-alone Flash Player:
Microsoft Windows
FlexMojos will attempt to launch the FlashPlayer.exe binary. To support execution of unit tests, add
the directory containing FlashPlayer.exe to your PATH or pass in the location of the FlashPlayer.exe
binary to Maven using the
Macintosh OSX
FlexMojos will attempt to launch the "Flash Player" application. To support the execution of unit
tests, add the directory containing "Flash Player" to your PATH or pass the path to the executable
to option.
Unix (Linux, Solaris, etc.)
FlexMojos will attempt to launch the flashplayer executable. To support the execution of unit tests,
add the directory containing flashplayer to your PATH or pass the path to the executable to option.
Note
On a Linux machine, you will need to have X virtual framebuffer (Xvfb) installed to run unit tests in a
headless build. For more information about Xvfb, click here.
If you have been developing Flash Applications with Adobe Flash CS4 or Adobe Flex Builder or if you
Maven: The Complete Reference
246 / 316
have been viewing flash content in a browser, you probably have the Flash Player installed somewhere on
your workstation. While it is possible to configure Maven to use one of these players for Flex unit tests,
you’ll want to make sure that you are running the debug version of the Flash Player. To minimize the
potential for incompatibility, you should download one of the Flash Player’s listed below and install it on
your local workstation. To download the standalone Flash Player for you environment:
• Windows: http://download.macromedia.com/pub/flashplayer/updaters/10/flashplayer_10_sa_debug.exe
• Mac OSX: http://download.macromedia.com/pub/flashplayer/updaters/10/flashplayer_10_sa_debug.app.zip
• Linux: http://download.macromedia.com/pub/flashplayer/updaters/10/flash_player_10_linux_dev.tar.gz
To install this player and add it to your PATH on an OSX machine, run the following commands:
$ wget http://download.macromedia.com/pub/flashplayer/updaters/10/\
flashplayer_10_sa_debug.app.zip
$ unzip flashplayer_10_sa_debug.app.zip
$ sudo cp -r Flash\ Player.app /Applications/
$ export PATH=/Applications/Flash\ Player.app/Contents/MacOS:${PATH}
Instead of adding the path for the Flash Player to your PATH on the command-line, you should configure
your environment to automatically configure these variables. If you are using bash, you would add the
last export command to your ~/.bash_profile.
13.2.4
Adding FlexMojos to Your Maven Settings’ Plugin Groups
If you need to run FlexMojos goals from the command-line, it will be more convenient if you add the
Sonatype Plugin groups to your Maven Settings. To do this, open up ~/.m2/settings.xml and add the
following plugin groups:
Adding Sonatype Plugins to Maven Settings
com.sonatype.maven.pluginsorg.sonatype.plugins
Once you’ve added these plugin groups to your Maven Settings you can invoke a FlexMojos goal using the
plugin prefix flexmojos. Without this configuration, calling the flexbuilder goal would involve
the following command-line:
Maven: The Complete Reference
247 / 316
$ mvn org.sonatype.flexmojos:flexmojos-maven-plugin:${flexmojos.version}: ←flexbuilder
With the org.sonatype.plugins group in your Maven settings, the same goal can be invoked with:
$ mvn flexmojos:flexbuilder
13.3
Creating a Flex Mojos Project from an Archetype
Flexmojos has a set of archetypes which can be used to quickly create a new Flex project. The following
archetypes are all in the org.sonatype.flexmojos group with a version of ${flexmojos.ver
sion}:
flexmojos-archetypes-library
Creates a simple Flex Library project which produces a SWC
flexmojos-archetypes-application
Creates a simple Flex Application with produces a SWF
flexmojos-archetypes-modular-webapp
Creates a Multimodule project which consists of a project that produces a SWC which is consumed
by a project which produces a SWF that is ultimately presented in a project that generates a WAR
13.3.1
Creating a Flex Library
To create a Flex Library Project, execute the following command at the command-line:
$ mvn archetype:generate \
-DarchetypeRepository=http://repository.sonatype.org/content/groups/public ←\
-DarchetypeGroupId=org.sonatype.flexmojos \
-DarchetypeArtifactId=flexmojos-archetypes-library \
-DarchetypeVersion=${flexmojos.version}
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: ’archetype’.
[INFO] com.sonatype.maven.plugins: checking for updates from central
...
Maven: The Complete Reference
248 / 316
[INFO] [archetype:generate]
[INFO] Generating project in Interactive mode
[INFO] Archetype defined by properties
...
Define value for groupId: : +org.sonatype.test+
Define value for artifactId: : +sample-library+
Define value for version: 1.0-SNAPSHOT: : +1.0-SNAPSHOT+
Define value for package: org.sonatype.test: : +org.sonatype.test+
Confirm properties configuration:
groupId: org.sonatype.test
artifactId: sample-library
version: 1.0-SNAPSHOT
package: org.sonatype.test
Y: : +Y+[INFO] Parameter: groupId, Value: org.sonatype.test
[INFO] Parameter: packageName, Value: org.sonatype.test
[INFO] Parameter: basedir, Value: /Users/Tim
[INFO] Parameter: package, Value: org.sonatype.test
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: artifactId, Value: sample-library
[INFO] ←------------------------------------------------------------------------ ←[INFO] BUILD SUCCESSFUL
If you look in the directory sample-library/ you will see that the project consists of the directory structure
shown in Figure 13.4.
Maven: The Complete Reference
249 / 316
Figure 13.4: Flexmojo Library Archetype File Structure
The product of the simple Flex library archetype only contains three files: a POM, one source, and a unit
test. Let’s examine each of these files. First, the Project Object Model (POM).
Project Object Model for Flex Library Archetype
4.0.0org.sonatype.testsample-library1.0-SNAPSHOTswc
Maven: The Complete Reference
sample-library Flexsrc/main/flexsrc/test/flexorg.sonatype.flexmojosflexmojos-maven-plugin3.5.0truecom.adobe.flex.frameworkflex-framework3.2.0.3958pomcom.adobe.flexunitflexunit0.85swctestm2em2e.versionorg.maven.ide.eclipselifecycle-mapping0.9.9-SNAPSHOTcustomizable
250 / 316
Maven: The Complete Reference
251 / 316
org.apache.maven.plugins:maven- ←resources-plugin::
org.apache.maven.pluginsmaven-resources-plugin2.4
Project Object Model for Flex Library Archetype is very simple, the key to this POM is the flexmojosmaven-plugin configuration which sets extensions to true. This configuration customizes the
lifecycle for the swc packaging which is defined in the flexmojos-maven-plugin. The archetype
then includes the flex-framework dependency and the flexmojos-unittest-support testscoped dependency. The flex-framework dependency is a POM which contains references to the
SWC libraries and resources required to compile Flex applications.
In Project Object Model for Flex Library Archetype, the packaging is very critical. A POMs packaging type controls the lifecycle it uses to produce build output. The value swc in the packaging element is Maven’s cue to look for the Flex-specific lifecycle customizations which are provided by the
flexmojos-maven-plugin. The other important part of this POM is the build element which specifies the location of the Flex source code and the Flex unit tests. Next, let’s take a quick look at Flex
Library Archetype’s Sample App Class which contains the sample Actionscript which was created by this
archetype.
Maven: The Complete Reference
252 / 316
Flex Library Archetype’s Sample App Class
package org.sonatype.test {
public class App {
public static function greeting(name:String):String {
return "Hello, " + name;
}
}
}
While this code is underwhelming, it does provide you with a quick model and a quick pointer: "Place
More Code Here". While it might seem silly to test code this simple, a sample test named TestApp.as is
provides in the src/test/flex directory. This test is shown in Unit Test for Library Archetype’s App Class.
Unit Test for Library Archetype’s App Class
package org.sonatype.test {
import flexunit.framework.TestCase;
public class TestApp extends TestCase {
/**
* Tests our greeting() method
*/
public function testGreeting():void {
var name:String = "Buck Rogers";
var expectedGreeting:String = "Hello, Buck Rogers";
var result:String = App.greeting(name);
assertEquals("Greeting is incorrect", expectedGreeting, result ←);
}
}
}
To run this build, go to the sample-library project directory and run mvn install.
$ mvn install
[INFO] Scanning for projects...
[INFO] ←------------------------------------------------------------------------ ←[INFO] Building sample-library Flex
[INFO]task-segment: [install]
[INFO] ←------------------------------------------------------------------------ ←-
Maven: The Complete Reference
253 / 316
[INFO] [resources:resources]
[INFO] [flexmojos:compile-swc]
[INFO] flexmojos ${flexmojos.version} - GNU GPL License (NO WARRANTY) - \
See COPYRIGHT file
[WARNING] Nothing expecified to include. Assuming source and resources ←folders.
[INFO] Flex compiler configurations:
-compiler.headless-server=false
-compiler.keep-all-type-selectors=false
-compiler.keep-generated-actionscript=false
-compiler.library-path ~/.m2/repository/com/adobe/flex/framework/flex/\
3.2.0.3958...
-compiler.namespaces.namespace http://www.adobe.com/2006/mxml
target/classes/configs/mxml-manifest.xml
-compiler.optimize=true
-compiler.source-path src/main/flex
...
[INFO] [resources:testResources]
[WARNING] Using platform encoding (MacRoman actually) to copy filtered \
resources, i.e. build is platform dependent!
[INFO] skip non existing resourceDirectory src/test/resources
[INFO] [flexmojos:test-compile]
[INFO] flexmojos ${flexmojos.version} - GNU GPL License (NO WARRANTY) - \
See COPYRIGHT file
[INFO] Flex compiler configurations:
-compiler.include-libraries ~/.m2/repository/org/sonatype/flexmojos/\
flexmojos-unittest-support...
-compiler.keep-generated-actionscript=false
-compiler.library-path ~/.m2/repository/com/adobe/flex/framework/flex
3.2.0.3958/flex-3.2.0....
-compiler.optimize=true
-compiler.source-path src/main/flex target/test-classes src/test/flex
-compiler.strict=true
-target-player 9.0.0
-use-network=true
-verify-digests=true -load-config=
[INFO] Already trust on target/test-classes/TestRunner.swf
[INFO] [flexmojos:test-run]
[INFO] flexmojos ${flexmojos.version} - GNU GPL License (NO WARRANTY) - \
See COPYRIGHT file
[INFO] flexunit setup args: null
[INFO] ←------------------------------------------------------------------------ ←[INFO] Tests run: 1, Failures: 0, Errors: 0, Time Elpased: 0 sec
[INFO] [install:install]
Maven: The Complete Reference
254 / 316
Note
To execute Flex unit tests you will need to configure your PATH environment variable to include the Flash
Player. For more information about configuring FlexMojos for unit tests, see Section 13.2.3.
When you ran mvn install on this project, you should notice in the output that Maven and Flexmojos
plugin is take care of managing all of the libraries and the dependencies for the Flex compiler. Much like
Maven excels at helping Java developers manage the contents of a Java classpath, Maven can help Flex
developers manage the complex of compile paths. You also might have been shocked when the Flexmojos
project started a web browser or the Flash Player and used it to execute the TestApp.as class against the
project’s source code.
13.3.2
Creating a Flex Application
To create a Flex application from a Maven archetype, execute the following command:
$ mvn archetype:generate \
-DarchetypeRepository=http://repository.sonatype.org/content/groups/ ←public\
-DarchetypeGroupId=org.sonatype.flexmojos \
-DarchetypeArtifactId=flexmojos-archetypes-application \
-DarchetypeVersion=${flexmojos.version}
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: ’archetype’.
[INFO] com.sonatype.maven.plugins: checking for updates from central
...
[INFO] [archetype:generate]
[INFO] Generating project in Interactive mode
[INFO] Archetype defined by properties
...
Define value for groupId: : +org.sonatype.test+
Define value for artifactId: : +sample-application+
Define value for version: 1.0-SNAPSHOT: : +1.0-SNAPSHOT+
Define value for package: org.sonatype.test: : +org.sonatype.test+
Confirm properties configuration:
groupId: org.sonatype.test
artifactId: sample-library
version: 1.0-SNAPSHOT
package: org.sonatype.test
Y: : +Y+
[INFO] Parameter: groupId, Value: org.sonatype.test
[INFO] Parameter: packageName, Value: org.sonatype.test
[INFO] Parameter: basedir, Value: /Users/Tim/flex-sample
[INFO] Parameter: package, Value: org.sonatype.test
Maven: The Complete Reference
255 / 316
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: artifactId, Value: sample-application
[INFO] BUILD SUCCESSFUL
If you look in the directory sample-application/ you will see the filesystem shown in Figure 13.5.
Figure 13.5: Directory Structure for Flex Application Archetype
Building an application from the Application archetype produces the following POM.
POM for Flex Application Archetype
4.0.0org.sonatype.test
Maven: The Complete Reference
sample-application1.0-SNAPSHOTswfsample-application Flexsrc/main/flexsrc/test/flexorg.sonatype.flexmojosflexmojos-maven-plugin3.5.0truecom.adobe.flex.frameworkflex-framework3.2.0.3958pomcom.adobe.flexunitflexunit0.85swctestm2em2e.versionorg.maven.ide.eclipselifecycle-mapping
256 / 316
Maven: The Complete Reference
257 / 316
0.9.9-SNAPSHOTcustomizable
org.apache.maven.plugins:maven- ←resources-plugin::
org.apache.maven.pluginsmaven-resources-plugin2.4
The difference between POM for Flex Application Archetype and Project Object Model for Flex Library
Archetype is that the packaging element is swf instead of swc. By setting the packaging to swf,
the project will produce a Flex application in target/sample-application-1.0-SNAPSHOT.swf. The sample application created by this archetype displays the Text "Hello World". Main.mxml can be found in
src/main/flex.
Sample Application Main.mxml
Maven: The Complete Reference
258 / 316
This application also creates a simple FlexUnit test that does nothing more than print out a trace message.
The sample unit test is in src/test/flex/org/sonatype/test.
Unit Test for Main.mxml
package org.sonatype.test
{
import flexunit.framework.TestCase;
import Main;
public class TestApp extends TestCase
{
public function testNothing():void
{
//TODO un implemented
trace("Hello test");
}
}
}
13.3.3
Creating a Multi-module Project: Web Application with a Flex
To create a multi-module project consisting of a Flex Library project referenced by a Flex Application,
referenced by a Web Application.
$ mvn archetype:generate \
-DarchetypeRepository=http://repository.sonatype.org/content/groups/ ←public\
-DarchetypeGroupId=org.sonatype.flexmojos \
-DarchetypeArtifactId=flexmojos-archetypes-modular-webapp \
-DarchetypeVersion=${flexmojos.version}
[INFO] Scanning for projects...
[INFO] Searching repository for plugin with prefix: ’archetype’.
[INFO] com.sonatype.maven.plugins: checking for updates from central
...
[INFO] [archetype:generate]
[INFO] Generating project in Interactive mode
[INFO] Archetype defined by properties
...
Define value for groupId: : +org.sonatype.test+
Define value for artifactId: : +sample-multimodule+
Define value for version: 1.0-SNAPSHOT: : +1.0-SNAPSHOT+
Define value for package: org.sonatype.test: : +org.sonatype.test+
Maven: The Complete Reference
259 / 316
Confirm properties configuration:
groupId: org.sonatype.test
artifactId: sample-library
version: 1.0-SNAPSHOT
package: org.sonatype.test
Y: : +Y+
[INFO] Parameter: groupId, Value: org.sonatype.test
[INFO] Parameter: packageName, Value: org.sonatype.test
[INFO] Parameter: basedir, Value: /Users/Tim
[INFO] Parameter: package, Value: org.sonatype.test
[INFO] Parameter: version, Value: 1.0-SNAPSHOT
[INFO] Parameter: artifactId, Value: sample-multimodule
[INFO] ←------------------------------------------------------------------------ ←[INFO] BUILD SUCCESSFUL
If you look in the sample-multimodule/ directory, you will see a directory structure which contains three
projects swc, swf, and war.
Maven: The Complete Reference
260 / 316
Figure 13.6: Directory Structure for Flex Multimodule Archetype
The simple top-level POM in this multimodule project is shown in . It consists of module references to
the swc, swf, and war modules.
Top-level POM Created by Modular Web Application Archetype
4.0.0org.sonatype.testsample-multimodule1.0-SNAPSHOTpom
Maven: The Complete Reference
261 / 316
swcswfwar
The swc project has a simple POM that resembles the POM shown in Project Object Model for Flex Library Archetype. Note that the artifactId in this POM differs from the name of the module directory
and is swc-swc.
swc Module POM
4.0.0org.sonatype.testsample-multimodule1.0-SNAPSHOTorg.sonatype.testswc1.0-SNAPSHOTswcswc Librarysrc/main/flexsrc/test/flexorg.sonatype.flexmojosflexmojos-maven-plugin3.5.0trueen_US
Maven: The Complete Reference
262 / 316
com.adobe.flex.frameworkflex-framework3.2.0.3958pomcom.adobe.flexunitflexunit0.85swctestm2em2e.versionorg.maven.ide.eclipselifecycle-mapping0.9.9-SNAPSHOTcustomizable
org.apache.maven.plugins:maven- ←resources-plugin::
←-
Maven: The Complete Reference
263 / 316
org.apache.maven.pluginsmaven-resources-plugin2.4
The swf module’s POM resembles the POM in POM for Flex Application Archetype adding a dependency
on the swc-swc artifact. Note that the following POM defines an artifactId that differs from the
directory that stores the module; the artifactId in the following POM is swf-swf.
swf module POM
4.0.0org.sonatype.testsample-multimodule1.0-SNAPSHOTorg.sonatype.testswf1.0-SNAPSHOTswfswf Applicationsrc/main/flexsrc/test/flex
Maven: The Complete Reference
org.sonatype.flexmojosflexmojos-maven-plugin3.5.0trueen_UScom.adobe.flex.frameworkflex-framework3.2.0.3958pomcom.adobe.flexunitflexunit0.85swctestorg.sonatype.testswc1.0-SNAPSHOTswcm2em2e.versionorg.maven.ide.eclipse
264 / 316
Maven: The Complete Reference
265 / 316
lifecycle-mapping0.9.9-SNAPSHOTcustomizable
org.apache.maven.plugins:maven- ←resources-plugin::
org.apache.maven.pluginsmaven-resources-plugin2.4
When you declare a dependency on a SWC, you’ll need to specify the type of the dependency so that
Maven can locate the appropriate artifact in the remote or local repository. In this case, the swf-swf
project depends upon the SWC that is generated by the swc-swc project. When you add the dependency
to the swf-swf project, the FlexMojos plugin will add the appropriate SWC file to the Flex Compiler’s
library path.
Next, take a look at the simple POM in the war module.
war module POM
4.0.0sample-multimoduleorg.sonatype.test1.0-SNAPSHOTorg.sonatype.testwar1.0-SNAPSHOTwarorg.sonatype.flexmojosflexmojos-maven-plugin3.5.0copy-flex-resourcesorg.mortbay.jettymaven-jetty-plugin6.1.17org.sonatype.testswf1.0-SNAPSHOTswf
Maven: The Complete Reference
267 / 316
The POM shown in war module POM configures the FlexMojos plugin to execute the copy-flexresources goal for this project. The copy-flex-resources goal will copy SWF application
into the web application’s document root. In this project, running a build and creating a WAR will
copy the swf-swf-1.0-SNAPSHOT.swf file to the web application’s root directory in target/war-war-1.0SNAPSHOT.
To build the multimodule web application project, run mvn install from the top-level directory. This
should build the swc-swc, swf-swf, and war-war artifacts and product a WAR file in war’/target/warwar-1.0-SNAPSHOT.war’ which contains the swf-swf-1.0-SNAPSHOT.swf in the document root of the
web application.
Note
To execute Flex unit tests you will need to configure your PATH environment variable to include the Flash
Player. For more information about configuring FlexMojos for unit tests, see Section 13.2.3.
13.4
The FlexMojos Lifecycle
The FlexMojos Maven plugin customizes the lifecycle based on the packaging. If your project has a pac
kaging of type swc or swf, the FlexMojos plugin with execute a customized lifecycle if your plugin
configuration sets the extensions to true. Setting Plugin Extensions to True for Custom Flex Lifecycle
shows the plugin configuration for the flexmojos-maven-plugin with the extensions set to true.
Setting Plugin Extensions to True for Custom Flex Lifecycle
src/main/flexsrc/test/flexorg.sonatype.flexmojosflexmojos-maven-plugin${flexmojos.version}
*true*
en_US
Maven: The Complete Reference
268 / 316
13.4.1
The SWC Lifecycle
When the packaging is swc, FlexMojos will execute the lifecycle shown in Figure 13.7. The highlighted
goals are goals from the FlexMojos plugin, the goals which are not highlights are standard goals from the
Core Maven plugins.
Figure 13.7: The FlexMojos SWC Lifecycle
The FlexMojos contributed goals are:
flexmojos:compile-swc
Maven: The Complete Reference
269 / 316
This goal compiles all of the Actionscript and MXML files in the sourceDirectory into a
SWC. A SWC is an Adobe library or class file which contains components and resources used in
Flex applications.
flexmojos:test-compile
This goal compiles all of the Actionscript and MXML files in the testSourceDirectory.
flexmojos:test-run
This goal executes unit tests using the Flash Player. This goal can only run if the Flash Player has
been configured as described in Section 13.2.3.
13.4.2
The SWF Lifecycle
When the packaging is swf, FlexMojos will execute the lifecycle shown in Figure 13.8. The highlighted
goals are goals from the FlexMojos plugin, the goals which are not highlights are standard goals from the
Core Maven plugins.
Maven: The Complete Reference
270 / 316
Figure 13.8: The FlexMojos SWF Lifecycle
The FlexMojos contributed goals are:
flexmojos:compile-swf
This goal compiles all of the Actionscript and MXML files in the sourceDirectory into a
SWF. A SWF is a file which contains an application that can be render by the Adobe Flash Player
or Adobe AIR software.
flexmojos:test-compile
This goal compiles all of the Actionscript and MXML files in the testSourceDirectory.
flexmojos:test-run
This goal executes unit tests using the Flash Player. This goal can only run if the Flash Player has
been configured as described in Section 13.2.3.
Maven: The Complete Reference
13.5
271 / 316
FlexMojos Plugin Goals
The FlexMojos Maven Plugin contains the following goals:
flexmojos:asdoc
Generates documentation for Actionscript source files
flexmojos:asdoc-report
Generates documentation for Actionscript sources as a report that can be included in a Maven site
flexmojos:compile-swc
Compiles Flex source (Actionscript and MXML) into a SWC library for use in a Flex or AIR
application
flexmojos:compile-swf
Compiles Flex source (Actionscript and MXML) into a SWF for use in the Adobe Flash Player or
Adobe AIR Runtime
flexmojos:copy-flex-resources
Copies Flex resources into a web application project
flexmojos:flexbuilder
Generates project files for use in Adobe Flex Builder
flexmojos:generate
Generates Actionscript 3 based on Java classes using Granite GAS3
flexmojos:optimize
Goal which run post-link SWF optimization on swc files. This goal is used to produce RSL files.
flexmojos:sources
Create a JAR which contains all the sources for a Flex project
flexmojos:test-compile
Compile all test classes in a Flex project
flexmojos:test-run
Run the tests using the Adobe Flash Player
flexmojos:test-swc
Build a SWC containing the test classes for a specific project
flexmojos:wrapper
Generate an HTML wrapper for a SWF application
Maven: The Complete Reference
13.5.1
272 / 316
Generating Actionscript Documentation
You can run the asdoc or asdoc-report goals to generate documentation for Actionscript. Once the goals
has completed, the documentation will be saved to ${basedir}/target/asdoc as HTML. Figure 13.9 shows
the result of running the asdoc goal against the Flexmojos application archetype project.
Figure 13.9: Actionscript Documentation Generated by the FlexMojos Plugin
13.5.2
Compiling Flex Source
FlexMojos contains a number of goals which compile Actionscript and MXML into SWCs and SWFs.
The compile-swc and compile-swf goals are used to generate output from a project’s source, and testcompile is used to compile unit tests. In the simple projects created by the FlexMojos archetypes, the
compile-swc and compile-swf goals are called because the project customizes the lifecycle and binds either compile-swc or compile-swf to the compile phase and test-compile to the test-compile phase. If you
need to configure the options for the FlexMojos compiler, you would configure the FlexMojos plugin configuration. For example, if you wanted the application with the POM shown in POM for Flex Application
Maven: The Complete Reference
273 / 316
Archetype to ignore certain code-level warnings on compile and use some customized font settings, you
might use the plugin configuration shown in Customizing the Compiler Plugin.
Customizing the Compiler Plugin
src/main/flexsrc/test/flexorg.sonatype.flexmojosflexmojos-maven-plugin${flexmojos.version}truetruetruefalsetruetrueU+0020-U+007E
${basedir}/src/main/resources/fonts.ser
flash.fonts.BatikFontManager201000
13.5.3
Generating Flex Builder Project Files
To generate Flex Builder project files for a FlexMojos project, configure the plugin groups as described
in Section 13.2.4, and run the flexbuilder goal:
Maven: The Complete Reference
274 / 316
$ mvn flexmojos:flexbuilder
Running this goal will create a .project, .settings/org.eclipse.core.resources.prefs, .actionScriptProperties,
and .flexLibProperties.
13.6
FlexMojos Plugin Reports
The FlexMojos Maven Plugin contains the following report:
flexmojos:asdoc-report
Generates documentation for Actionscript sources as a report that can be included in a Maven site
13.6.1
Generating Actionscript Documentation Report
To generate the asdoc-report as part of your Maven site build, add the following XML to your POM:
Configuring the Actionscript Documentation Report
org.sonatype.flexmojosflexmojos-maven-plugin${flexmojos.version}flex-reportsasdoc-report
Maven: The Complete Reference
275 / 316
When you run mvn site, Maven will generate this report and place the results under the "Project
Reports" menu as shown in Figure 13.10.
Figure 13.10: Actionscript Documentation Report on Maven Site
If you need to pass in any configuration options to the asdoc-report, you will need add a configuration
element to the reportSets element as shown in Configuring the asdoc-report.
Configuring the asdoc-report
org.sonatype.flexmojosflexmojos-maven-plugin${flexmojos.version}flex-reportsasdoc-reportMy TEST API Doc
Maven: The Complete Reference
276 / 316
13.7
Developing and Customizing Flexmojos
The following sections guide you through some of first steps toward customizing or contributing to the
Flexmojos project. Flexmojos is more than just a tool for people who are interested in compiling Actionscript into SWF and SWC artifacts, it is a community of developers. This section isn’t for everyone, but,
if you have an itch to scratch and you wish to participate, come on in.
13.7.1
Get the Flexmojos Source Code
Flexmojos is an open source project hosted on the Sonatype Forge, and the source code for Flexmojos
is stored in the Sonatype Forge Subversion repository. You can browse the contents of the Flexmojos
Subversion repository by opening http://svn.sonatype.org/flexmojos/trunk in a web browser.
Maven: The Complete Reference
277 / 316
Figure 13.11: Flexmojos Subversion Repository
If you are interested in participating in the Flexmojos project, you will likely want to checkout the current
Flexmojos source code to your local machine. To checkout the Flexmojos source using Subversion,
execute the following command at the command line:
$ svn co http://svn.sonatype.org/flexmojos/trunk flexmojos
A flexmojos
...
$ ls
COPYRIGHT
flexmojos-sandbox pom.xml
flexmojos-archetypesflexmojos-super-poms src
flexmojos-maven-plugin flexmojos-testing
flexmojos-parentflexmojos-touchstone
Maven: The Complete Reference
278 / 316
Chapter 14
Android Application Development with
Maven
14.1
Introduction
Android is an open source mobile phone and embedded device operating system developed by the Open
Handset Alliance. It is based on a Linux kernel with a virtual machine environment for managed application code using Java bytecode for the runtime code generation. The development environment is based on
the Java language and JVM/JDK based tooling. The generated Java bytecode is transformed into Dalvik
executable code optimized for constrained devices. Once deployed to the device and executed the code
will run on the Dalvik virtual machine. Java is the default programming language and the API’s are all
Java based.
In most cases, development of Android applications is done within the Eclipse based Android Development Toolkit ADT. The optionally generated Apache Ant based build can be used to build applications
outside the IDE. The Android Maven Plugin was created to allow development teams to build, deploy and
release Android applications with Apache Maven, taking advantage of all the powerful features available
like dependency management, reporting, code analysis and much more.
Tip
The Android Maven Plugin is rapidly evolving. The documentation below applies to version 3.0.0-alpha12 and higher. For up to date information refer to the plugin website.
Maven: The Complete Reference
14.2
279 / 316
Configuring Build Environment for Android Development
Before you attempt to build your Android libraries and applications with Maven, you will need to install
the Android SDK and potentially install the Android API jar files into your local Maven repository or
your repository server.
14.2.1
Installing the Android SDK
The Android Maven Plugin requires the presence of the Android SDK in your development environment.
Install the SDK following the directions on the Android Developer web site.
The ANDROID_HOME environment variable should be configured to point to the installation directory of
the Android SDK. For example if the SDK is installed in /opt/android-sdk-linux this can be achieved with
export ANDROID_HOME=/opt/android-sdk-linux
on a Unix/bash based system or
set ANDROID_HOME=C:\opt\android-sdk-linux
on a Windows system.
In addition to the SDK, the various platform versions you need for development should also be installed
following the instructions. You can install a subset of available platforms or simply install all available
versions.
Optionally, the path ANDROID_HOME/tools and ANDROID_HOME/platform-tools can be added
to the PATH variable to allow easy command line execution of the various tools provided with the SDK.
Maven: The Complete Reference
14.2.2
280 / 316
Android artifact install into Maven repository
When building an Android application with Maven the compile process needs access to the Android
API for the specific platform version the project is configured against. The Android SDK ships this as
android.jar files in the different platform folders. In order for Maven to access these libraries, they need
to be available in the local Maven repository.
Typically artifacts are available in Maven Central, however only the platform versions available in the
Android Open Source Project are published to Maven Central. Newer versions of the platform as well as
the compatibility package and proprietary extensions like the Google Maps support are not available there
and need to be published to your Maven repository, if you want to use them in your Android project.
The artifacts published to Maven central are available as dependencies under the groupId com.google.
android with the artifactId android and android-test.
The Maven Android SDK Deployer has been created to publish artifacts from the Android SDK into your
local repository or repository server when using components that are not available in Central.
Download the tool by clicking on the Download Source button and extract the downloaded zip or
tar archive in a folder of your choice. A folder with a naming pattern of mosabua-maven-android-sdkdeployer-XXX with XXX being a revision number like df824df will be created.
14.2.2.1
Installation to local repository
In order to install the android jar files from the different platform revisions into your local repository you
run the command in the deployer folder.
cd mosabua-maven-android-sdk-deployer-df824df
mvn clean install
By default this will install all android.jar, maps.jar, usb.jar files and the compatibilty packages into
your local Maven repository. You should find all newly installed files in the android, com.goo
gle.android.maps, com.android.future and android.support group identifiers under
~/.m2/repository.
Maven: The Complete Reference
14.2.2.2
281 / 316
Installation to remote repository
The above deployment works fine for one machine, but if you need to supply a whole team of developers
and a cluster of build machines with the artifacts, you will want to deploy the artifacts once to a remote
repository server that is available to all users. If you are not currently using a repository manager, you
should download Nexus and configure a user with permission to deploy artifacts to a repository. To get
started with Nexus, read the Nexus Installation chapter in the free, online Nexus book.
As a first step you will need to edit the repo.url property in the pom.xml in the top folder of the
Maven Android SDK Deployer tool to point to the repository you want to publish to. Alternatively you
can provide this property in the settings file or with -Drepo.url=theurl on the command line.
Then you need to add a server with the correct access credentials for the server to your Maven Settings
file.
Snippet for settings.xml for the repository server access credentials
android.repoyour usernameyour password
Once that configuration is completed, you can deploy the artifacts with the command mvn deploy. As
a result you should find the artifact in the repository of your remote server.
14.2.2.3
Installation of a subset of all platforms
By default the Maven Android SDK Deployer tool will attempt to install or deploy all versions of the
platforms artifacts into a repository. If you decide to only install a subset of the components the tool can
be used with profile options to only install or deploy some artifacts. This can be done by specifying the
platform API versions as a profile name.
mvn install -P 3.2
Maven: The Complete Reference
282 / 316
Further details are available in the Maven Android SDK Deployer documentation.
14.3
Getting Started
The HelloFlashlight example application serves as a starting point to introduce you to the usage of the
Android Maven Plugin. The code for the helloflashlight example application as well as various more
complex examples are available as part of the plugin samples project.
To enable a Maven based build of an Android project a pom.xml has to be added in the root folder of the
project:
The HelloFlashlight pom.xml file
4.0.0com.simpligility.androidhelloflashlight1.0.0-SNAPSHOTapkHelloFlashlightcom.google.androidandroid1.6_r2provided${project.artifactId}srccom.jayway.maven.plugins.android.generation2 ←android-maven-plugin3.0.0-SNAPSHOT
Maven: The Complete Reference
283 / 316
truecom.jayway.maven.plugins.android.generation2 ←groupId>
android-maven-plugintrue416true
The highlights of this pom.xml are:
• the packaging type of apk
• the dependency to the Android platform jar
• and the build configuration with the Android Maven Plugin
The Android Package packaging type apk is what activates the Android-specific lifecycle modifications of the Android Maven Plugin. It takes care of all the specific calls to the Android SDK tools, that
process resources, convert Java bytecode and so on. The Android Maven Plugin needs to be configured
with extensions set to true for this to work as visible in the pluginManagement section.
The declared dependency to the android platform jar is available in Maven Central with various platform
versions. Alternatively you could use an Android jar from the Maven Android SDK Deployer with the
modified groupId and artifactId. The documentation of the deployer shows all valid dependencies.
The scope of provided is important. It signals to Maven that the contents of the jar will not need to be
Maven: The Complete Reference
284 / 316
packaged into the application package, because they are available at runtime on the device as part of the
environment.
In addition the android jar artifacts only contain exception throwing stubs for all methods in order to
define the API for the compiler. They can not be executed on the development machine, but rely on an
emulator or device runtime environment.
The configuration of the Android Maven Plugin is done in the build section. Initially only the sdk platform
parameter is required to be specified. You can use either a platform version number or a API level number
as documented on the Android developer documentation.
Tip
The version of the Android Maven Plugin in the pom file is a development version. Replace it with
the latest released version, when running the example yourself or download the stable branch of the
samples.
To build the application and run it on an already started emulator or attached device you could use
mvn install android:deploy android:run
14.4
Creating New Projects with the Android Maven Archetypes
When starting a fresh project it is easy to use the Maven Archetype Plugin to create a skeleton to start
working with. Fortunately multiple archetypes for Android projects are available.
You can create a new android-quickstart project, which is similar to the helloflashlight example on the
command line with
mvn archetype:generate \
-DarchetypeArtifactId=android-quickstart \
-DarchetypeGroupId=de.akquinet.android.archetypes \
-DarchetypeVersion=1.0.6 \
-DgroupId=your.company \
-DartifactId=my-android-application
Other archetypes available are an Android project including test execution with the archetypeArtifactId
Maven: The Complete Reference
285 / 316
android-with-test-archetype and a project with release process configuration android-rel
ease-archetype.
Note
Many developmemt environments have a visual integration of creating new projects with a Maven
archetype, so you can use that instead of the command line.
14.5
Using Add-Ons
For many applications the normal Android SDK artifact (android.jar) will be sufficient, however some
applications require add-ons. One of the more commonly used add-ons is the Google Maps add-on, which
provides access to the Google Maps API. The Maps add-on is deployed to your Maven repository by the
Maven Android SDK Deployer tool. To use an add on you just have to add the respective dependency to
your pom file.
The dependency to the Google Maps API
com.google.android.mapsmaps7_r1provided
Another common add-on is the compatibility library. It needs to be included in the produced apk and
there does not have provided scope.
The dependency to the compatibility library for API v4 and up
android.supportcompatibility-v4r3
Maven: The Complete Reference
14.6
286 / 316
Multi Module Android Projects
The Android Maven Plugin can be used in a multi-module project setup. An example setup would be 3
different modules linked via a parent pom.
Java Library Code
This first module could contain any business logic implemented in Java, or any other JVM based
language actually, in a jar package.
Android Application Code
This second module would depend on the first module and consist of all the interface code for the
Android platform. It would need to use apk packaging and the Maven Android Plugin.
Instrumentation Test
This third module would depend on the second module and implement the integration test of the
application.
Together with the use of other modules to separate items it is possible to set up a multi module build for
an Android application as well as a server side web application sharing e.g. the code for the core objects
and business logic.
A comprehensive example setup like this called morseflash is part of the samples project for the plugin.
14.7
Using external dependencies
When using the Android Maven Plugin there are three types of dependencies that are treated differently.
Regular dependencies to other Java libraries
The Java byte code files (.class) of library dependencies as denoted in the normal Maven way are
transformed to dalvik executable format like any source code of the current project and included in
the Android package. All other files are included as contained in the source library. An example
would look like this
com.simpligilitymodel0.1
Maven: The Complete Reference
287 / 316
Dependencies to other Android projects
Other Maven Android projects with packaging type apk declared as dependencies are deployed to
the emulator prior to running the instrumentation tests in the integration test phase.
com.simpligility.androidintents0.1apk
Dependencies to other Android projects’ sources
Other Android Maven projects with packaging type apk declared as source dependencies are pulled
into the current Android application with assets and resources and used to build an application
combining all artifacts including resources.
com.simpligility.androidtools0.1apklib
Tip
A common use case for using Android libraries is to separate out all application code that is independent
of the application store in which the apk will be made available. Then you can have one apk per store that
depends on the library and add any specific code for e.g. market access or release build requirements.
14.8
The Custom Lifecycle from the Android Maven Plugin
The Android Maven Plugin customizes the lifecycle based on the packaging. If your project has a pack
aging of type apk the customized lifecycle will be used.
The customized lifecycle has the following additional executions in the default lifecycle.
Maven: The Complete Reference
288 / 316
generate-sources Phase
Use the Android Asset Packaging Tool (aapt) of the platform version specified in the pom to
package the Android specific resources like AndroidManifest.xml, assets and resources. Additional parameters can be passed to aapt with the parameter aaptExtraArgs.
process-classes Phase
Run the dx tool of the platform version specified in the pom to convert all classes (libraries, resources and project code) into davlik executable format.
package Phase
Run the Android Package tool (apk) of the Android SDK to create and sign the Android package
file (apk) for installation on the emulator or device.
pre-integration-test Phase
Deploy the currently built Android application package (apk) as well as any other dependencies
with packaging type apk to the emulator/device.
integration-test Phase
Run the instrumentation test classes against the deployed application.
14.9
Plugin Configuration Parameters
The Android Maven Plugin supports a large number of configuration parameters. They can typically be
passed into the execution as plugin configuration, as properties defined in the pom or settings file or as
command line parameters.
An example of a plugin configuration
2.121-no-skin
Configuration as properties in pom.xml
21
Maven: The Complete Reference
289 / 316
Configuration on command line invocation
mvn android:emulator-start -Dandroid.emulator.avd=21
A number of other parameters have defaults that point to the default location as used by the standard
Android/Eclipse project layout, but can be customized if desired.
• androidManifestFile
• assetsDirectory
• resourceDirectory
• sourceDirectories
Some of the other useful parameters are
device
Specify usb, emulator or a specific serial number. Read Section 14.10 for more information.
undeployBeforeDeploy
This parameter will cause the application as well as the test application to be undeployed from the
device before each deployment.
14.10
Device Interaction
The Android Maven Plugin has powerful features for interacting with attached devices and emulators
implemented in a number of goals. They use the android.device parameter to determine a specific
device as specified by the serial number, all connected emulators or all connected devices should be
affected. A value of emulator will trigger execution on all emulators connected via adb and a value of
usb will affect all devices.
The following goals support the device parameter and sequential execution against all devices.
android:deploy
The deploy goal deploys the built apk file, or another specified apk, to the connected device(s).
This goal is automatically performed when running through the integration-test lifecycle
Maven: The Complete Reference
290 / 316
phase on a project with instrumentation tests (e.g. mvn install or mvn integrationtest).
android:undeploy
The undeploy goal removes the apk of the current project, or another specified apk, from the
connected devices and emulators.
android:redeploy
The redeploy goal executes undeploy and deploy consecutively on all specified devices and
emulators.
android:instrument
The instrument goal runs the instrumentation tests after automatically deploying the test application and the tests. It honors the standard Maven skip test properties as well as android.test.
skip. It supports a number of further parameters that are explained in more detail in Section 14.14.
android:pull
The pull goal can be used to copy a file or directory from the device. Source and destination file
have to be specified with the android.pull.source and android.pull.destination
configuration parameters.
android:push
The push goal can be used to copy a file or directory to the device. Configuration is done with the
android.push.source and android.push.destination parameters.
android:run
The run goal will start the application on the device. If the run.debug paramter is set to true starting
will wait for a debugger to connect.
14.11
Emulator Interaction
The emulator-start goal can start an existing Android device emulator. The start up can be configured with the parameters emulator.avd specifying the name of the virtual device, emulator.wait
specifying a wait period and emulator.options specifying further command line options passed to
the emulator command.
The emulator-stop and emulator-stop-all goals stop the specified or all attached Android
emulator(s).
Maven: The Complete Reference
14.12
291 / 316
Other Useful Android Maven Plugin Goals
A number of plugin goals are useful for manual execution or custom binding to a lifecycle phase e.g. in a
release profile.
14.12.1
Manifest-update
The manifest-update goal can be used to do in place updates to the AndroidManifest.xml file. It can
update a number of parameters like versionName, versionCode and others and supports the parameters
manifest.versionName, manifest.versionCode, manifest.versionCodeAutoIncr
ement, manifest.versionCodeUpdateFromVersion, manifest.sharedUserId and man
ifest.debuggable.
14.12.2
Zipalign
The zipalign goal can execute the zipalign command as required for creation an apk for upload to the
Android Market. It supports the parameters zipalign.skip, zipalign.verbose, zipalign.
inputApk and zipalign.outputApk.
14.12.3
Help
The help goal provides overall as well as plugin goal specific help on the command line.
14.13
Internal Android Maven Plugin Goals
The Android Maven Plugin supports a number of goals that are part of the default lifecycle and are invoked
automatically. In most cases you will not have to invoke these goals directly, but it can be useful to know
about them and their configuration options.
android:apk
Maven: The Complete Reference
292 / 316
The apk goal creates the android package (apk) file. By default the plugin signs the file with the
debug keystore. The configuration parameter false can be
used to disable the signing process.
android:deploy-dependencies
The deploy-dependencies goal deploys all directly declared dependencies of a
pk in this project. This goal is usually used in a project with instrumentation tests, to
deploy the apk to test onto the device before running the deploying and running the instrumentation
tests apk. The goal is automatically performed when running through the integration-test life cycle phase on a project with instrumentation tests (e.g. mvn install or mvn integrationtest).
android:dex
The dex goal converts compiled Java classes to the Android Dalivk Executable (dex) format. The
dex execution can be configured with the parameters dex.jvmArguments, dex.coreLibr
ary, dex.noLocals and dex.optimize.
android:generate-sources
The generate-sources goal generates R.java based on the resources specified by the resources configuration parameter. It generates Java files based on aidl files. If the configuration parameter deleteConflictingFiles is true (which it is by default), this goal has also deletes
any R.java files found in the source directory, deletes any .java files with the same name as an .aidl
file found in the source directory and deletes any Thumbs.db files found in the resource directory.
android:internal-integration-test
The internal-integration-test goal is called automatically when the lifecycle reaches
the integration-test phase. It determines whether to call the goal instrument in this phase
based on the existence of instrumentation test classes in the current project. The goal is internal to
the plugin lifecycle and should not be used as separate invocation on the command line.
android:internal-pre-integration-test
The internal-pre-integration-test goal is called automatically when the lifecycle
reaches pre-integration-test phase. It determines whether to call the goals android:
deploy-dependencies and android:deploy in this phase and if necessary invokes them.
The goal is internal to the plugin lifecycle and should not be used as separate invocation on the
command line.
14.14
Testing Android Application Code
Testing Android Application code can be done in a unit test fashion with rich junit support as part of the
Android SDK as well as integration type testing called instrumentation testing.
Maven: The Complete Reference
14.14.1
293 / 316
Unit tests
The Android Maven Plugin includes the execution of the Surefire plugin and as such unit tests can be
included in the project like in any other project. The default path for test classes in the Eclipse and
therefore Android Development Toolkit is test and therefore Maven has to be configured to access code
from there with the configuration
Adding the test folder to the build configuration
test
...
Alternatively the Maven conventions can be implemented by moving the source code for the application
and the test source code into src/main/java and src/test/java and reconfiguring the Eclipse
project files.
14.14.2
Instrumentation tests
Instrumentation tests are integration tests bundled into an application that run on the emulator or device
and interact with another deployed application to test the behaviour. The common setup to run instrumentation tests would be two parallel projects, one for the application and one for the instrumentation tests.
These modules are tied together as modules of a parent pom.
The Android Maven Plugin samples contains the morseflash as well as theapidemos-15 examples for a
project set up in this manner. The setup of the instrumentation test application with the Android Maven
Plugin is the same as for a normal application with the added dependency to the application that needs to
be tested. It is important to add the type of apk to the dependency to allow the Android Maven Plugin
to find the Android package of the application.
com.simpligility.androidintents0.1apk
Instrumentation test execution supports a large number of configuration parameters that are displayed in
the plugin configuration layout in Available parameters for instrumentation testing.
Maven: The Complete Reference
294 / 316
Available parameters for instrumentation testing
true|false|autopackageNameclassNametrue|falsetrue|falsetrue|false avd
small|medium|largetrue|falseyour.package.name.YourTestClassyour.package.name
Unless createreport is set to false the instrumentation test run will produce junit xml compatible
test output in the build output folder for test results target/surefire-reports for each device or
emulator the tests run on.
14.15
Native Application Builds
The Android Maven Plugin supports building application that include native code as well. Define the
environment variable ANDROID_NDK_HOME to point to the required Android NDK installation and
have a look at the native projects in the samples of the plugin for more details.
14.16
Tips and Tricks
14.16.1
Other Maven Plugins
Apart from the features of the Android Maven Plugin you have access to all the other Maven plugins to
automate things like license header file checks, resource filtering and many more.
Maven: The Complete Reference
14.16.2
295 / 316
Performing a Release Build
A release build for an Android application needs to create an apk file that has been signed and zipaligned.
In addition it is adviseable to run shrinking and obfuscation. All these steps can be done with the Maven
Jarsigner Plugin, the Proguard Maven Plugin and the zipalign goal of the Android Maven Plugin. A
sample configuration of a release build is available in the morseflash example application of the plugin
samples.
14.16.3
Configuring command line usage
In order to use the Android Maven Plugin goals on the command line with the short plugin name andr
oid outside a directory that contains a reference to the plugin, you have to add the following pluginG
roups snippet to your settings.xml file.
Snippet for settings.xml to enable short plugin name usage
com.jayway.maven.plugins.android.generation2
Maven: The Complete Reference
296 / 316
Chapter 15
Appendix: Settings Details
15.1
Quick Overview
The settings element in the settings.xml file contains elements used to define values which configure
Maven execution. Settings in this file are settings which apply to many projects and which should not
be bundled to any specific project, or distributed to an audience. These include values such as the local
repository location, alternate remote repository servers, and authentication information. There are two
locations where a settings.xml file may live:
• Maven Installation Directory: $M2_HOME/conf/settings.xml
• User-specific Settings File: ~/.m2/settings.xml
Here is an overview of the top elements under settings:
Overview of top-level elements in settings.xml
Maven: The Complete Reference
297 / 316
15.2
Settings Details
15.2.1
Simple Values
Half of the top-level settings elements are simple values, representing a range of values which configure
the core behavior of Maven:
Simple top-level elements in settings.xml
${user.dir}/.m2/repositorytruefalsefalseorg.codehaus.mojo
...
The simple top-level elements are:
localRepository
Maven: The Complete Reference
298 / 316
This value is the path of this build system’s local repository. The default value is ${user.dir}/.m2/repository.
interactiveMode
true if Maven should attempt to interact with the user for input, false if not. Defaults to true.
usePluginRegistry
true if Maven should use the ${user.dir}/.m2/plugin-registry.xml file to manage plugin versions,
defaults to false.
offline
true if this build system should operate in offline mode, defaults to false. This element is useful
for build servers which cannot connect to a remote repository, either because of network setup or
security reasons.
pluginGroups
This element contains a list of pluginGroup elements, each contains a groupId. The list is
searched when a plugin is used and the groupId is not provided in the command line. This list
contains org.apache.maven.plugins by default.
15.2.2
Servers
The distributionManagement element of the POM defines the repositories for deployment. However, certain settings such as security credentials should not be distributed along with the pom.xml. This
type of information should exist on the build server in the settings.xml.
Server configuration in settings.xml
...
server001my_loginmy_password${user.home}/.ssh/id_dsasome_passphrase664775
Maven: The Complete Reference
299 / 316
...
The elements under server are:
id
This is the id of the server (not of the user to login as) that matches the distributionManag
ement repository element’s id.
username, password
These elements appear as a pair denoting the login and password required to authenticate to this
server.
privateKey, passphrase
Like the previous two elements, this pair specifies a path to a private key (default is ${user.home}/.ssh/id_dsa)
and a passphrase, if required. The passphrase and password elements may be externalized in the
future, but for now they must be set plain-text in the settings.xml file.
filePermissions, directoryPermissions
When a repository file or directory is created on deployment, these are the permissions to use. The
legal values of each is a three digit number corresponding to *nix file permissions, i.e. 664, or 775.
15.2.3
Mirrors
Mirror configuration in settings.xml
...
planetmirror.comPlanetMirror Australiahttp://downloads.planetmirror.com/pub/maven2central
...
Maven: The Complete Reference
300 / 316
id, name
The unique identifier of this mirror. The id is used to differentiate between mirror elements.
url
The base URL of this mirror. The build system will use prepend this URL to connect to a repository
rather than the default server URL.
mirrorOf
The id of the server that this is a mirror of. For example, to point to a mirror of the Maven central
server (http://repo1.maven.org/maven2), set this element to central. This must not match the mirror
id.
15.2.4
Proxies
Proxy configuration in settings.xml
...
myproxytruehttpproxy.somewhere.com8080proxyusersomepassword*.google.com|ibiblio.org
...
id
The unique identifier for this proxy. This is used to differentiate between proxy elements.
active
true if this proxy is active. This is useful for declaring a set of proxies, but only one may be active
at a time.
Maven: The Complete Reference
301 / 316
protocol, host, port
The protocol://host:port of the proxy, separated into discrete elements.
username, password
These elements appear as a pair denoting the login and password required to authenticate to this
proxy server.
nonProxyHosts
This is a list of hosts which should not be proxied. The delimiter of the list is the expected type of
the proxy server; the example above is pipe delimited - comma delimited is also common.
15.2.5
Profiles
The profile element in the settings.xml is a truncated version of the pom.xml profile element. It consists
of the activation, repositories, pluginRepositories and properties elements. The
profile elements only include these four elements because they concern themselves with the build system
as a whole (which is the role of the settings.xml file), not about individual project object model settings.
If a profile is active from settings, its values will override any equivalent profiles which matching identifiers in a POM or profiles.xml file.
15.2.6
Activation
Activations are the key of a profile. Like the POM’s profiles, the power of a profile comes from its
ability to modify some values only under certain circumstances; those circumstances are specified via an
activation element.
Defining Activation Parameters in settings.xml
...
testfalse
Maven: The Complete Reference
302 / 316
1.5Windows XPWindowsx865.1.2600mavenVersion2.0.3${basedir}/file2.properties${basedir}/file1.properties
...
...
Activation occurs when all specified criteria have been met, though not all are required at once.
jdk
activation has a built in, Java-centric check in the jdk element. This will activate if the test is run
under a jdk version number that matches the prefix given. In the above example, 1.5.0_06 will
match.
os
The os element can define some operating system specific properties shown above.
property
The profile will activate if Maven detects a property (a value which can be dereferenced within the
POM by ${name}) of the corresponding name=value pair.
file
Finally, a given filename may activate the profile by the existence of a file, or if it is missing.
The activation element is not the only way that a profile may be activated. The settings.xml file’s
activeProfile element may contain the profile’s id. They may also be activated explicitly through
the command line via a comma separated list after the P flag (e.g. -P test).
To see which profile will activate in a certain build, use the maven-help-plugin.
Maven: The Complete Reference
303 / 316
mvn help:active-profiles
15.2.7
Properties
Maven properties are value placeholder, like properties in Ant. Their values are accessible anywhere
within a POM by using the notation ${X}, where X is the property. They come in five different styles, all
accessible from the settings.xml file:
+env.+X
Prefixing a variable with env. will return the shell’s environment variable. For example, ${env.PATH}
contains the $path environment variable. (%PATH% in Windows.)
+project.+x
A dot-notated (.) path in the POM will contain the corresponding elements value.
+settings.+x
A dot-notated (.) path in the settings.xml will contain the corresponding elements value.
Java system properties
All properties accessible via java.lang.System.getProperties() are available as POM
properties, such as ${java.home}.
x
Set within a properties element or an external file, the value may be used as ${someVar}.
Setting the ${user.install} property in settings.xml
...
...
${user.dir}/our-project
...
Maven: The Complete Reference
304 / 316
...
The property ${user.install} is accessible from a POM if this profile is active.
15.2.8
Repositories
Repositories are remote collections of projects from which Maven uses to populate the local repository of
the build system. It is from this local repository that Maven calls it plugins and dependencies. Different
remote repositories may contain different projects, and under the active profile they may be searched for
a matching release or snapshot artifact.
Repository Configuration in settings.xml
...
...
codehausSnapshotsCodehaus Snapshotsfalsealwayswarntrueneverfailhttp://snapshots.maven.codehaus.org/maven2default
...
Maven: The Complete Reference
305 / 316
...
...
releases, snapshots
These are the policies for each type of artifact, Release or snapshot. With these two sets, a POM has
the power to alter the policies for each type independent of the other within a single repository. For
example, one may decide to enable only snapshot downloads, possibly for development purposes.
enabled
true or false for whether this repository is enabled for the respective type (releases or snapshots).
updatePolicy
This element specifies how often updates should attempt to occur. Maven will compare the local POMs timestamp to the remote. The choices are: always, daily (default), interval:X
(where X is an integer in minutes) or never.
checksumPolicy
When Maven deploys files to the repository, it also deploys corresponding checksum files. Your
options are to ignore, fail, or warn on missing or incorrect checksums.
layout
In the above description of repositories, it was mentioned that they all follow a common layout.
This is mostly correct. Maven 2 has a default layout for its repositories; however, Maven 1.x had
a different layout. Use this element to specify which if it is default or legacy. If you are upgrading
from Maven 1 to Maven 2, and you want to use the same repository which was used in your Maven
1 build, list the layout as legacy.
15.2.9
Plugin Repositories
The structure of the pluginRepositories element block is similar to the repositories element.
The pluginRepository elements each specify a remote location of where Maven can find plugins
artifacts.
Plugin Repositories in settings.xml
...
...
...
codehausSnapshotsCodehaus Snapshotsfalsealwayswarntrueneverfailhttp://snapshots.maven.codehaus.org/maven2default
...
...
15.2.10
Active Profiles
Setting active profiles in settings.xml
...
env-test
Maven: The Complete Reference
307 / 316
The final piece of the settings.xml puzzle is the activeProfiles element. This contains a set of
activeProfile elements, which each have a value of a profile id. Any profile id defined as an act
iveProfile will be active, regardless of any environment settings. If no matching profile is found
nothing will happen. For example, if env-test is an activeProfile, a profile in a pom.xml
(or profile.xml with a corresponding id it will be active. If no such profile is found then execution will
continue as normal.
15.2.11
Encrypting Passwords in Maven Settings
Once you start to use Maven to deploy software to remote repositories and to interact with source control
systems directly, you will start to collect a number of passwords in your Maven Settings and without
a mechanism for encrypting these passwords, a developer’s ~/.m2/settings.xml will quickly become a
security risk as it will contain plain-text passwords to source control and repository managers. Maven
2.1 introduced a facility to encrypt passwords in a user’s Maven Settings (~/.m2/settings.xml). To do this,
you must first create a master password and store this master password in a security-settings.xml file in
~/.m2/settings-security.xml. You can then use this master password to encrypt passwords stored in Maven
Settings (~/.m2/settings.xml).
To illustrate this feature, consider the process Maven uses to retrieve an unencrypted server password for
a user’s Maven Settings as shown in Figure 15.1. A user will reference a named server using an identifier
in a project’s POM, Maven looks for a matching server in Maven Settings. When it finds a matching
server element in Maven Settings, Maven will then use the password associated with that server element
and send this password along to the server. The password is stored as plain-text in ~/.m2/settings.xml and
it is readily available to anyone who has read access to this file.
Maven: The Complete Reference
308 / 316
Figure 15.1: Storing Unencrypted Passwords in Maven Settings
Next, consider the process Maven uses to support encrypted passwords as shown in Figure 15.2.
Maven: The Complete Reference
309 / 316
Figure 15.2: Storing Encrypted Passwords in Maven Settings
To configure encrypted passwords, create a master password by running mvn -emp or mvn --encr
ypt-master-password followed by your master password.
$ mvn -emp mypassword
{rsB56BJcqoEHZqEZ0R1VR4TIspmODx1Ln8/PVvsgaGw=}
Maven prints out an encrypted copy of the password to standard out. Copy this encrypted password and
paste it into a ~/.m2/settings-security.xml file as shown in
settings-security.xml with Master Password
{rsB56BJcqoEHZqEZ0R1VR4TIspmODx1Ln8/PVvsgaGw=}
Maven: The Complete Reference
310 / 316
After you have created a master password, you can then encrypt passwords for use in your Maven Settings.
To encrypt a password with the master password, run mvn -ep or mvn --encrypt-password.
Assume that you have a repository manager and you need to send a username of "deployment" and a
password of "qualityFIRST". To encrypt this particular password, you would run the following command:
$ mvn -ep qualityFIRST
{uMrbEOEf/VQHnc0W2X49Qab75j9LSTwiM3mg2LCrOzI=}
At this point, copy the encrypted password printed from the output of mvn -ep and paste it into your
Maven Settings.
Storing an Encrypted Password in Maven Settings (~/.m2/settings.xml)
nexusdeployment{uMrbEOEf/VQHnc0W2X49Qab75j9LSTwiM3mg2LCrOzI=} ←password>
...
When you run a Maven build that needs to interact with the repository manager, Maven will retrieve
the Master password from the ~/.m2/settings-security.xml file and use this master password to decrypt
the password stored in your ~/.m2/settings.xml file. Maven will then send the decrypted password to the
server.
What does this buy you? It allows you to avoid storing your passwords in ~/.m2/settings.xml as plaintext passwords providing you with the peace of mind that your critical passwords are not being stored,
unprotected in a Maven Settings file. Note that this feature does not provide for encryption of the password
while it is being sent to the remote server. An enterprising attacker could still capture the password using
a network analysis tool.
For an extra level of security, you can encourage your developers to store the encrypted master password
on a removable storage device like a USB hard drive. Using this method, a developer would plug a
removable drive into a workstation when she wanted to perform a deployment or interact with a remote
server. To support this, your ~/.m2/settings-security.xml file would contain a reference to the location of
the settings-security.xml file using the relocation element.
Configuring Relocation of the Master Password
Maven: The Complete Reference
311 / 316
/Volumes/usb-key/settings-security.xml
The developer would then store the settings-security.xml file at /Volumes/usb-key/settings-security.xml
which would only be available if the developer were sitting at the workstation.
Maven: The Complete Reference
312 / 316
Chapter 16
Appendix: Sun Specification Alternatives
The Apache Geronimo project maintains implementations of various enterprise Java specifications. Table 16.1 lists the artifactId and artifact version for all of the specifications implemented by the Geronimo
project. To use one of these dependencies, use a groupId of org.apache.geronimo.specs, locate
the version of the Specification you want to use and reference the dependency with the Artifact Id and
Artifact Version listed in Table 16.1.
Note
All artifacts in Table 16.1, have a groupId of org.apache.geronimo.specs.
Table 16.1: Alternate Spec Implementations Artifacts
Specification
Activation
Spec Version
1.0.2
Activation
1.1
Activation
1.0
CommonJ
1.1
Corba
2.3
Artifact Id
geronimoactivation_1.0.2_spec
geronimoactivation_1.1_spec
geronimoactivation_1.0_spec
geronimocommonj_1.1_spec
geronimocorba_2.3_spec
Artifact Version
1.2
1.0.1
1.1
1.0
1.1
Maven: The Complete Reference
313 / 316
Table 16.1: (continued)
Corba
3.0
EJB
2.1
EJB
3.0
EL
Interceptor
1.0
3.0
J2EE Connector
1.5
J2EE Deployment
1.1
J2EE JACC
1.0
J2EE Management
1.0
J2EE Management
1.1
J2EE
1.4
JACC
1.1
JEE Deployment
1.1MR3
JavaMail
1.3.1
JavaMail
1.4
JAXR
1.0
JAXRPC
1.1
JMS
1.1
JPA
3.0
JSP
2.0
JSP
2.1
JTA
1.0.1B
geronimo1.2
corba_3.0_spec
geronimo1.1
ejb_2.1_spec
geronimo1.0
ejb_3.0_spec
geronimo-el_1.0_spec 1.0
geronimo1.0
interceptor_3.0_spec
geronimo-j2ee1.1.1
connector_1.5_spec
geronimo-j2ee1.1
deployment_1.1_spec
geronimo-j2ee1.1.1
jacc_1.0_spec
geronimo-j2ee1.1
management_1.0_spec
geronimo-j2ee1.0
management_1.1_spec
geronimo1.1
j2ee_1.4_spec
geronimo1.0
jacc_1.1_spec
geronimo-javaee1.0
deployment_1.1MR3_spec
geronimo1.3
javamail_1.3.1_spec
geronimo1.2
javamail_1.4_spec
geronimo1.1
jaxr_1.0_spec
geronimo1.1
jaxrpc_1.1_spec
geronimo1.1
jms_1.1_spec
geronimo1.1
jpa_3.0_spec
geronimo1.1
jsp_2.0_spec
geronimo1.0
jsp_2.1_spec
geronimo1.1.1
jta_1.0.1B_spec
Maven: The Complete Reference
314 / 316
Table 16.1: (continued)
JTA
1.1
QName
1.1
SAAJ
1.1
Servlet
2.4
Servlet
2.5
STaX API
1.0
WS Metadata
2.0
geronimojta_1.1_spec
geronimoqname_1.1_spec
geronimosaaj_1.1_spec
geronimoservlet_2.4_spec
geronimoservlet_2.5_spec
geronimo-staxapi_1.0_spec
geronimo-wsmetadata_2.0_spec
1.1
1.1
1.1
1.1.1
1.1.1
1.0.1
1.1.1
Note
The version numbers in the Artifact Version column may be out of date by the time you read this book.
To check on the version number, visit http://repo1.maven.org/maven2/org/apache/geronimo/specs/ in a
web browser, and click on the artifactId you want to add. Choose the highest version of the spec you
want to depend upon.
To illustrate how one would use Table 16.1, if we wanted to write some code in our project which interacted with the JTA 1.0.1B specification, we would need to add the following dependency to our project:
Adding JTA 1.0.1B to a Maven Project
org.apache.geronimo.specsgeronimo-jta_1.0.1B_spec1.1.1
Notice how the version of the artifact isn’t going to line up with the version of the specification—the
previous dependency configuration adds version 1.0.1B of the JTA specification using the artifact version
of 1.1.1. Be aware of this when depending on the alternate Geronimo implementations, and always double
check that you are using the latest artifact version number for your specifications.
Maven: The Complete Reference
315 / 316
Chapter 17
Creative Commons License
This work is licensed under a Creative Commons Attribution-Noncommercial-No Derivative Works 3.0
United States license. For more information about this license, see http://creativecommons.org/licenses/by-nc-nd/3.0/us/. You are free to share, copy, distribute, display, and perform the work under the following
conditions:
• You must attribute the work to Sonatype, Inc. with a link to http://www.sonatype.com.
• You may not use this work for commercial purposes.
• You may not alter, transform, or build upon this work.
If you redistribute this work on a web page, you must include the following link with the URL in the
about attribute listed on a single line (remove the backslashes and join all URL parameters):
When downloaded or distributed in a jurisdiction other than the United States of America, this work
shall be covered by the appropriate ported version of Creative Commons Attribution-NoncommercialNo Derivative Works 3.0 license for the specific jurisdiction. If the Creative Commons AttributionNoncommercial-No Derivative Works version 3.0 license is not available for a specific jurisdiction, this
work shall be covered under the Creative Commons Attribution-Noncommercial-No Derivate Works version 2.5 license for the jurisdiction in which the work was downloaded or distributed. A comprehensive
list of jurisdictions for which a Creative Commons license is available can be found on the Creative
Commons International web site at http://creativecommons.org/international.
If no ported version of the Creative Commons license exists for a particular jurisdiction, this work shall be
covered by the generic, unported Creative Commons Attribution-Noncommercial-No Derivative Works
version 3.0 license available from http://creativecommons.org/licenses/by-nc-nd/3.0/.
Source Exif Data:
File Type : PDF
File Type Extension : pdf
MIME Type : application/pdf
PDF Version : 1.4
Linearized : No
Page Count : 339
Page Mode : UseOutlines
Author : Tim O'Brien, Manfred Moser, John Casey, Brian Fox, Jason Van Zyl, Eric Redmond, and Larry Shatzer
Title : Maven: The Complete Reference
Subject :
Creator : DBLaTeX-0.3.4-3
Producer : pdfTeX-1.40.14
Create Date : 2016:02:19 17:12:35-05:00
Modify Date : 2016:02:19 17:12:35-05:00
Trapped : False
PTEX Fullbanner : This is pdfTeX, Version 3.1415926-2.5-1.40.14 (TeX Live 2013/Debian) kpathsea version 6.1.1