For those familiar with the basics of Maven, here are some reminders regarding its use.
JAVA_HOME
to a local JDK, for example set JAVA_HOME=C:\jdk1.8.0
maven/bin
directory to the PATH
${user.home}/.m2/repository
mvn validate
- sanity-check for the pom.xml
file. (Each project has a pom.xml
file that controls the behaviour of Maven.)
mvn compile
mvn test
mvn package
mvn install
mvn dependency:analyze
is a good sanity check. It detects 2 kinds of error:
-Dmaven.test.skip=true
don't run the unit tests
-Pdev
run with a specific profile; profiles often carry data specific to a target environment
-X
verbose
-q
quiet
-l
where to put the output log file
-f
a custom name for the pom.xml
file
-e
verbose error reporting
mvn [options] [goal(s)] [phase(s)]
A simple jar app:
>mvn archetype:generate -DartifactId=my-app -DgroupId=com.mycompany.app -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=falseA web app:
>mvn archetype:generate -DartifactId=my-web-app -DgroupId=com.mycompany.app -DarchetypeArtifactId=maven-archetype-webapp -DinteractiveMode=falseFor the web-app archetype, the tree looks like this after you have also run
mvn install
:
├───src │ └───main │ ├───resources │ └───webapp │ └───WEB-INF └───target ├───classes ├───maven-archiver └───my-web-app ├───META-INF └───WEB-INF └───classes
Packaging: 'LP(P:)G' 1x Lifecycle Nx Phase Nx(plugin:)GoalPackaging settings:
jar
(the default)
pom
war
ear
rar
par
ejb
maven-plugin
There are 3 lifecycles. Here they are, listed with their phases:
pre-clean, clean, post-clean
validate, initialize, generate-sources, process-sources, generate-resources, process-resources, compile, process-classes,
generate-test-sources, process-test-sources, generate-test-resources, process-test-resources, test-compile, process-test-classes, test,
prepare-package, package, pre-integration-test, integration-test, post-integration-test, verify, install, deploy
pre-site, site, post-site, site-deploy
The phases in a lifecycle are ordered and cumulative: a later phase includes all earlier ones.
For example, invoking mvn install
will always cause all preceding phases in that lifecycle to be executed as well.
Typical invocations of Maven specify 1..N phases.
For example, mvn clean install
invokes 2 phases from 2 independent lifecycles.
Each phase, in turn, has N plugin:goal
's (much like an Ant target).
Each goal is implemented by a plugin.
You customize the behavior of a plugin by adding a <plugin>
entry in the pom.xml
.
Some important phases:
validate
- validate the project is correct and all necessary information is available
compile
- compile the source code
test
- run the unit tests
package
- create the build target (a jar, for example)
install
- put the build target into your local Maven repository
In the resources directory, files can have place-holder references of the form ${blah}
.
Values for those references are defined in:
pom.xml
profile settings (likely the most common location)
pom.xml
properties, as in ${project.name}
, for instance
main/filters/blah.properties
settings.xml
, a Maven config file, as in ${settings.blah}
${env.blah}
During the build, there is a maven phase (process-resources
) which finds resource files and does a find-and-replace on all such
${blah}
placeholder strings.
In the pom.xml
, you need to turn this mechanism on explicitly, like so:
<build> <resources> <resource> <directory>src/main/resources</directory> <filtering>true</filtering> </resource> </resources> </build>
coordinates
to refer to their conventional names for build
artifacts: the who-what-when information.
Example: myorg.myproj:abc-web:1.1.0
The colon acts as a separator. The 3 basic items are, in order:
groupId
who made this
artifactId
what is its name - avoid dots in this part
version
major.minor.increment.qualifier: 3.2.9, 3.2-beta
SNAPSHOT
has specific meaning to Maven: the build is a development build, not a release build.
There are variations in the version string, having these items appearing before the version:
**/*Test.java
**/Test*.java
**/*TestCase.java
main/resources
items are put into the root of the jar
test/resources
can be accessed in tests, as if they're in the root of the class path
artifactId
, because it may lead to problems.
pom.xml
, a standard version number, appearing as just 3.2, acts as advice to Maven.
Maven will try to use that version, as your preferred version, but it may, if needed, use a different version instead.
You alter this behaviour, and hard-code to a precise version, by decorating the version with a special syntax, for example [3.2]
.
Versions have a special syntax:
pom.xml
compile
(the default; all cases; propagated to child projects)
runtime
(run and test, but not compile)
test
(tests only)
provided
(compile and test, but not run). For example, the servlet API jars are provided by the container,
so they don't need to be included in the war.
>mvn install:install-file -Dfile=non-maven-proj.jar -DgroupId=some.group -DartifactId=non-maven-proj -Dversion=1 -Dpackaging=jar
pom.xml
:
Be aware of sloppy terms when reading docs about these ideas: the terms parent and child are used, but they should be avoided, because they mean different things according to who's talking. Your thinking will be clear if you stick to these terms instead:
<parent>
, and pointing to a super-pom
packaging
to pom
The effective-pom:
mvn help:effective-pom
is the command that shows the effective-pom
parent
tag.
dependency
, then your-pom gets that dependency
, no matter what.
dependencyManagement
item, then your-pom gets it only if your-pom explicitly declares it as a dependency
.
Furthermore, if your-pom's dependency
leaves out version/scope for the item, then it gets the super-pom's version/scope.
mvn -Pproduction clean install
pom.xml
<profile>
tag are visible during resource-filtering, so that placeholder
strings ${blah}
in resource files can be replaced with real values defined by the current profile.
Example of the syntax:
<profile> <id>production</id> <properties> <db.driverClass>oracle.jdbc.driver.OracleDriver</db.driverClass> <db.connectionURL>jdbc:oracle:thin:@10.0.1.14:1521:APPS</db.connectionURL> <db.username>productionuser</db.username> <db.password>productionpassword</db.password> </properties> </profile>
dependencyManagement
to centralize versions among modules
pluginManagement
, consider defining explicitly all versions of all plugins,
so you don't get clobbered by plugin upgrades (similar behaviour as for dependencyManagement
)