Vous êtes sur la page 1sur 53

Using Maven2

Free Maven Books

Better Builds with Maven Maven: The Definitive Guide (alpha)


www.mergere.com www.sonatype.com/book
The Maven Site

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;

public class MessagePrinter {


public void printMessage(String message, OutputStream os){
PrintWriter pw = new PrintWriter(os);
pw.print(message);
pw.flush();
}
}

public class Hello {


public static void main(String[] args){
ResourceBundle messages = ResourceBundle.getBundle("messages");
MessagePrinter mp = new MessagePrinter();
mp.printMessage(messages.getString("message1"), System.out);
mp.printMessage("\n", System.out);
}
}
My Application POM
<project ...>
...
<name>My Application</name>
<url>http://localhost:8080/my-app</url>
...
<build>
<plugins>
<plugin>
<artifactId>maven-jar-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>com.example.Hello</mainClass>
</manifest>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>
Eclipse Integration
 Maven2 plugin for Eclipse; either from project
root execute:

$ mvn eclipse:eclipse

and import with Eclipse, or create the project


in Eclipse and add the Maven2 project nature
Eclipse Integration
Ready for Take Off

$ 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 :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[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

$ java -jar my-app-1.0-SNAPSHOT.jar


Hello World!
Plugins & Goals

 A plugin contains one or more goals


(Goal a.k.a. Mojo; Maven + Pojo = Mojo ?!@!)
 A plugin is a Maven artifact
 A goal is uniquely referenced/invoked by:
groupId:artifactId:version:goal

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

2. Invoke goals bound to the lifecycle(s) up to and including


a phase:
$ mvn [options] phase... [parameter]...

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 :

Tests run: 1, Failures: 0, Errors: 0, Skipped: 0

[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

 Note for anyone trying this at home: there's a bit of classpath


config required to get this working nicely. It's easiest to run it
on the Eclipse console, and modify the target
messages.properties
Configuring Plugins
e.g. Ant
<project...>
...
<build>
<plugins>
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>generate-sources</phase>
<configuration>
<tasks>
<!--
Place any ant task here. You can add anything you can add
between <target> and </target> in a build.xml.
-->
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
Standard
Maven Plugins
Listed at: http://maven.apache.org/plugins/
clean changes assembly idea
compiler checkstyle dependency Codehaus:
deploy clover enforcer build-helper
install doap gpg castor
resources docck help javacc
site javadoc invoker jdepend
surefire jxr one native
verifier pmd plugin sql
ear project-info-reports release taglist
ejb surefire-report remote-resources Other:
jar ant repository cargo
rar antlr scm jaxme
war antrun source jetty
changelog archetype eclipse jalopy
POM Inheritance
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>my-app</artifactId>
<version>1.0-SNAPSHOT</version>
</project>

No source or target defined in


POM, yet this works:

$ 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>

To fully resolve the POM:


$ mvn help:effective-pom | less
POM Inheritance
<project>
<groupId>com.example</groupId>
<artifactId>org-pom</artifactId>
<version>1</version>
<!-- configure
JDK version, e.g: 1.5
standard reports, etc. -->
</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

 Checks for use of SNAPSHOT dependencies or plugins

 Runs $ mvn clean integration-test

 Requests release info:

 version numbers
 Creates new POMs:

 pom.xml for tag


 pom.xml for next version
 release-pom.xml
 Creates tag in SCM

$ mvn release:perform
 Uses release-pom.xml, deploys

project, generates site, etc.


Website / Reports (1)
 Project website:
 Conventions for structuring documentation,
supporting various formats: DocBook simple, FML,
XDOC, APT, Twiki
 Directory structure conventions, supporting multiple
types of documentation, e.g: public, user, developer,
etc.
 Configurable, skinnable site
 Project info from POM: contact details: organisation,
developers; SCM details, etc.
Website / Reports (2)
 Metrics, checks, and project reports (on website):
 Javadoc
 Test results
 Code coverage (Cobertura)
 Checkstyle, PMD, JDepend, Clirr
 Database documentation (Hibernate)
 Dependency report
 TODO report (//TODO, FIXME, configurable)
 Linked and line-numbered HTML sources
 Release notes and roadmap from issue tracker
Quick Tour
In Brief (1)
 Java EE support:
 WAR, EAR packaging
 Rapid web app development
 Integration (in container) testing
 Deployment to environments

 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?

Vous aimerez peut-être aussi