Académique Documents
Professionnel Documents
Culture Documents
http://maven.apache.org/
What is Maven?
Build lifecycle
Dependency management tool
Artifact repository
Collection of plugins
Project reporting tool
Set of conventions
Distilled experience
What Else is Maven?
Succinct command line tool
Designed for Java/Java EE/other
Holder/publisher of project documentation
Generator of project metrics
Customisable: environment, lifecycle, etc
Inheritable
Declarative
Encourager of modularity and reuse
Integrated with SCM tools
Integrated with IDEs
Integrated with Ant
System of repositories
Project kick starter
Release manager
Deployer
Enabler of portable build knowledge
Encourager of best practice
Community
Not perfect
Quick Start
Download Maven2, unzip, add bin directory to $PATH
Configure proxy in ~/.m2/settings.xml if required
$ mvn archetype:create \
-DgroupId=com.example \
-DartifactId=my-app
Directory Structure
Convention
Java sources:
src/main/java
Unit tests:
src/test/java
pom.xml
pom.xml –
The Project Object Model
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>my-app</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>my-app</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>
Directory Structure Convention
Added:
My app sources
Properties file:
src/main/resources/
messages.poperties
My unit test
Killer App
package com.example;
$ mvn eclipse:eclipse
$ mvn package
stdout
[INFO] Scanning for projects...
[INFO] ----------------------------------------------------------------------------
[INFO] Building My Application
[INFO] task-segment: [package]
[INFO] ----------------------------------------------------------------------------
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:compile]
[INFO] Compiling 1 source file to /home/russell/Desktop/maven-presentation/example/my-app/target/classes
[INFO] [resources:testResources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:testCompile]
[INFO] Compiling 1 source file to /home/russell/Desktop/maven-presentation/example/my-app/target/test-classes
[INFO] [surefire:test]
[INFO] Surefire report directory: /home/russell/Desktop/maven-presentation/example/my-app/target/surefire-reports
-------------------------------------------------------
TESTS
-------------------------------------------------------
Running com.example.AppTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.022 sec
Results :
[INFO] [jar:jar]
[INFO] Building jar: /home/russell/Desktop/maven-presentation/example/my-app/target/my-app-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3 seconds
[INFO] Finished at: Wed Jul 04 11:11:55 NZST 2007
[INFO] Final Memory: 4M/11M
[INFO] ------------------------------------------------------------------------
The (Almost)
Finished Product
Classes and test classes
compiled
Resources copied to
classes directory
Test reports created
Jar file created
e.g: org.apache.maven.plugins:maven-eclipse-plugin:eclipse
defaults shorten this to: eclipse:eclipse
Anatomy of a Maven Command
1. Invoke a specific goal:
$ mvn [options] plugin:goal [parameter]...
e.g:
$ mvn -e eclipse:eclipse
-> Generate Eclipse configuration, print verbose error messages
e.g:
$ mvn clean package -Dmaven.test.skip=true
-> Clean target, build package, skip tests
Maven Lifecycles
Three built-in lifecycles:
default
clean
site
You can create your own lifecycle, but only if
you have really weird build requirements!
The Default Build Lifecycle
Project Packaging
<project ...>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>my-app</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
...
</project>
Lifecycle Bindings
Build Lifecycle
$ mvn package
stdout
[INFO] Scanning for projects...
[INFO] ----------------------------------------------------------------------------
[INFO] Building My Application
[INFO] task-segment: [package]
[INFO] ----------------------------------------------------------------------------
[INFO] [resources:resources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:compile]
[INFO] Compiling 1 source file to /home/russell/Desktop/maven-presentation/example/my-app/target/classes
[INFO] [resources:testResources]
[INFO] Using default encoding to copy filtered resources.
[INFO] [compiler:testCompile]
[INFO] Compiling 1 source file to /home/russell/Desktop/maven-presentation/example/my-app/target/test-classes
[INFO] [surefire:test]
[INFO] Surefire report directory: /home/russell/Desktop/maven-presentation/example/my-app/target/surefire-reports
-------------------------------------------------------
TESTS
-------------------------------------------------------
Running com.example.AppTest
Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.022 sec
Results :
[INFO] [jar:jar]
[INFO] Building jar: /home/russell/Desktop/maven-presentation/example/my-app/target/my-app-1.0-SNAPSHOT.jar
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESSFUL
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 3 seconds
[INFO] Finished at: Wed Jul 04 11:11:55 NZST 2007
[INFO] Final Memory: 4M/11M
[INFO] ------------------------------------------------------------------------
Dependencies
<project ...>
...
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies> Explicitly declared, including version
</project> Resolved by Maven, not required in project
directory / source control repository
Scoped: compile, provided, runtime, test
SNAPSHOT dependencies updated
Transitive
Strictly acyclic (a DAG not a tree)
Killer App Reloaded
public class Hello {
public static void main(String[] args) {
ReloadableResourceBundleMessageSource messages
= new ReloadableResourceBundleMessageSource();
messages.setCacheSeconds(1);
messages.setBasename("messages");
MessagePrinter mp = new MessagePrinter();
Scanner scanner = new Scanner(System.in);
do {
String message = messages.getMessage("message1", null,
Locale.getDefault());
mp.printMessage(message, System.out);
mp.printMessage("\n", System.out);
mp.printMessage("Keep playing? [Y/n]\n", System.out);
} while (!"n".equals(scanner.nextLine()));
}
}
Dependencies
<project ...>
...
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-context</artifactId>
<version>[2.0,)</version>
<exclusions>
<exclusion>
<groupId>org.springframework</groupId>
<artifactId>spring-aop</artifactId>
</exclusion>
...
</project>
Version ranges
Use exclusions to trim unwanted
dependencies
Transitive Dependencies
Reloadable Message Source
Hello World!
Keep playing? [Y/n]
y
Hello Again World!
Keep playing? [Y/n]
n
$ mvn compile
Super POM
<project>
<build>
...
<outputDirectory>target/classes</outputDirectory>
...
<sourceDirectory>src/main/java</sourceDirectory>
...
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
...
</build>
</project>
<project>
<parent>
<groupId>com.example</groupId>
<artifactId>org-pom</artifactId>
<version>1</version>
</parent>
<groupId>com.example</groupId>
<artifactId>my-app</artifactId>
...
</project>
Maven Repositories
Repositories store artifacts:
plugins
project dependencies
Central:
http://repo1.maven.org/maven2
(or mirror)
Local: ~/.m2/repository
The first execution of a plugin,
or requirement for a
dependency pulls the artifact
from central and caches it
locally
Maven Repositories
Problems:
Reliant on network and
external repository for
dependencies and plugins
Can't deploy to Central
Maven repository for reuse
as dependencies of other
projects (though usually
wouldn't want to)
Organisation Repository
No longer reliant on network
or external repository for
dependencies and plugins
Can deploy to organisation
repository in order to share
artifacts
Multiple repository
configurations possible
Multiple repository tools
available: Archiva, Proximity,
Artifactory
Archiva
Install and Deploy
$ mvn deploy
Install and Deploy
$ mvn deploy
SCM Integration
Fully implemented:
Bazaar
CVS
Mercurial
Perforce
StarTeam
Subversion
CM Synergy
Partially implemented:
ClearCase
File system
Visual Source Safe
Configuring SCM
<project>
<groupId>com.example</groupId>
<artifactId>my-app</artifactId>
...
<scm>
<connection>
scm:svn:http://example.com/svn-read/my-app/trunk
</connection>
<developerConnection>
scm:svn:http://example.com/svn-dev/my-app/trunk
</developerConnection>
<url>
http://example.com/view.cvs
</url>
</scm>
</project>
SCM Integration,
What For?
Use SCM agnostic commands:
$ mvn scm:checkin -Dmessage="to the cause"
$ mvn scm:update
Project bootstrapping: $ mvn scm:bootstrap
Available for use by Maven tools, e.g:
documented and linked in project website,
published in Archiva summary
Continuous Integration, SCM details located in
project rather than CI tool
Release management
Cutting a Release
$ mvn release:prepare [-DdryRun=true]
Checks SCM for modifications
version numbers
Creates new POMs:
$ mvn release:perform
Uses release-pom.xml, deploys
Multi-module projects
Enable / encourage reuse between projects
Maven inter-module dependency eliminates cycles
between modules
Nicely supported in NetBeans
Not nicely supported in Eclipse – nested projects
In Brief (2)
Continuous Integration:
CruiseControl
Continuum
Reuses project information as defined in POM
Profiles
Build activity carried out under different conditions,
e.g: personal requirements, dev / test / release,
continuous integration
Maven settings
Help
Problems
History: Maven 1, might have left a bad taste
Steep learning curve
Once you've got it, the knowledge is portable to
other projects built with Maven
Complex needs require complex configuration
Alan Kay: Simple things should be simple.
Complex things should be possible
Verbose XML config
Docs aren't great, but getting better
Error messages often do not provide much (or any)
detail (e.g. archetype problem)
Ensuring the project is buildable and testable in the
IDE as well as with Maven can be complex
Multi-module projects not supported by Eclipse (but
they are in Netbeans)
Stuff to Look at
Buildr – a build system configured in Ruby
that reuses parts of Maven:
repositories;
directory structure conventions;
Rake – a Ruby build tool
Still Interested?
Get reading and enjoy the ride
Questions?