Using Maven2. Free Maven Books Maven: The Definitive Guide (alpha) Better Builds with Maven .

Post on 16-Jan-2016

237 views 0 download

Tags:

Transcript of Using Maven2. Free Maven Books Maven: The Definitive Guide (alpha) Better Builds with Maven .

Using Maven2

Free Maven Books

Maven: The Definitive Guide (alpha)www.sonatype.com/book

Better Builds with Mavenwww.mergere.com

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 StructureConvention

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 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); }}

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

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

------------------------------------------------------- T E S T S-------------------------------------------------------Running com.example.AppTestTests 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.jarHello 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:eclipsedefaults 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

------------------------------------------------------- T E S T S-------------------------------------------------------Running com.example.AppTestTests 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></project>

Explicitly declared, including version 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 SourceHello World!Keep playing? [Y/n]yHello 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 Pluginse.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>

StandardMaven Plugins

cleancompilerdeployinstallresourcessitesurefireverifierearejbjarrarwarchangelog

changescheckstylecloverdoapdocckjavadocjxrpmdproject-info-reportssurefire-reportantantlrantrunarchetype

assemblydependencyenforcergpghelpinvokeronepluginreleaseremote-resourcesrepositoryscmsourceeclipse

ideaCodehaus:build-helpercastorjavaccjdependnativesqltaglistOther:cargojaxmejettyjalopy

Listed at: http://maven.apache.org/plugins/

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> <parent> <groupId>com.example</groupId> <artifactId>org-pom</artifactId> <version>1</version> </parent> <groupId>com.example</groupId> <artifactId>my-app</artifactId> ...</project>

<project> <groupId>com.example</groupId> <artifactId>org-pom</artifactId> <version>1</version> <!-- configure JDK version, e.g: 1.5 standard reports, etc. --></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?