maven 2 in the real world
DESCRIPTION
How to effectively employ Maven2 on large scale projectsTRANSCRIPT
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Object Oriented and beyond
Maven 2 in the real world
Carlo [email protected]
JUG Genova
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Maven2: love it or hate it?
● Widespread build platform– used by many open source and commercial projects
● PROs– automatic dependency management– good tool/IDE support– automate the entire build life cycle– highly configurable
● CONs– highly configurable :-)– too much XML...
also... lots of tutorials
on simple cases, less documentation
on complex builds
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Presentation goals
● Maven can be your friend (and save lots of time!)– if you
● learn it and understand it ● use it in the right way
● My talk is about how to maximize usefulness and efficiency – while minimizing complexity & overhead
● Sharing real world experience – in designing and managing the build process for
several large projects (>20 modules, >100 kLoc)
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Part 1
Maven2 in 5 minutes
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Maven2 in 5 minutes
● Maven is a modular automation system built around 4 main elements
– input: project src/resources + POM – output: tested and packaged artifact
Maven
POM
repository
Pluginssrc
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Maven in 5': the POM
● The Project Object Model describes– project coordinates– project type
● packaging (JAR, WAR, EAR, POM)– source structure– build phases
● standard + custom– dependencies– plugins
groupId: net.juggenovaartifactId: sample
version: 1.0
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Maven in 5': build lifecycle
● Default life cycle– validate – generate-sources– process-resources– compile – test-compile – test– package – integration-test – verify – install – deploy
– (some skipped for clarity)
● Every goal implies all the previous ones
– mvn compile– actually executes
– validate – generate-sources– process-resource– compile
● Stand-alone goals– mvn scm:update
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Maven in 5':Dependency Management
● Dependencies– include all external libraries and files needed to
completely assemble the output● JARs, WARs, ZIPs, POMs
– are versioned– can be transitive
● e.g. include just spring, get commons-logging automatically
● Conflict resolution mechanism– determines the version to be used when a jar is
included multiple times
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Maven in 5': repositories
● Maven repository– a structured store containing artifacts (JAR, WAR, ZIP...)
● Maven uses at leas two– local repository – on your PC – central repository – http://repo1.maven.org/maven2/
● Three types of repositories– plain filesystem folder– folder served by HTTP daemon
● populated via SCP/FTP/WEBDAV– full “intelligent” repository (with indexing, search, cache, ...)
local repository
${user.home}/.m2/repository
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
From code to repo (and back)
local repository
central repository
remoterepository
install
deploy
packageresolve
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Part 2
Effective maven2
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Getting the most out of Maven
● Good old sw engineering principles still apply!● Don't repeat yourself
– the DRY principle● reduce time, effort, maintenance ● minimize the impact of changes
● Separate concerns● Automate as much as possible● Use the right tools (plugins & repositories)● Keep the build fast
things always change
in a project
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
How to minimize XML
● Exploit the three main POM relationships– inheritance, aggregation, dependency
● This is a valid (and working) maven POM– <project xmlns="..." xmlns:xsi="..." xsi:schemaLocation="...">
● <modelVersion>4.0.0</modelVersion>● <groupId>net.juggenova.sample</groupId>● <artifactId>minimal</artifactId>● <version>1.0</version>
– </project>● How can this work?
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
The Super POM
● Implicitely, all POMs inherit from the Super POM– see http://maven.apache.org/pom.html
● Defines– standard directory structure– default plugins & repo
– where it is? inside mvn jars– how to check it?
– mvn help:effective-pom● Convention over Configuration
SuperPOM
yourPOM
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
The Super-POM
<repos itories> <repos itory> <id>central</id> <name>Maven Repos itory S witchboard</name> <url>http://repo1.maven.org/maven2</url> </repos itory> </repos itories> <build> <sourceDirectory>src/main/java</sourceDirectory> <tes tS ourceDirectory>src/tes t/java</tes tS ourceDirectory> <outputDirectory>target/classes</outputDirectory> ... <resources> <resource> <directory>src/main/resources</directory> </resource> </resources> <tes tResources>...</testResources>
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
The Super-POM
<pluginManagement> <plugins> <plugin> <artifactId>maven-assembly-plugin</artifactId> <vers ion>2.2-beta-1</vers ion> </plugin> <plugin> <artifactId>maven-compiler-plugin</artifactId> <vers ion>2.0.2</vers ion> </plugin>
... </plugins> </pluginManagement> </build>
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Parent POM: make you own
● Create a POM defining your project conventions and tools
– additional resource directories– default plugin configuration
● e.g. custom configuration for maven-compiler-plugin– standard libraries
● e.g. default spring version with – <dependencyManagement>
– repositories and deployment config ● e.g. your company repository with – <distributionManagement>
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
net.juggenova.sample:parent
<build> <sourceDirectory>java/src</sourceDirectory> ... <pluginManagement> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <configuration> <source>1.6</source> <target>1.6</target> </configuration> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId>
<configuration>...</configuration> </plugin> </plugins>
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Parent POM: use it
● Reference the parent at the beginning of a POM– <parent>
● <artifactId>parent</artifactId>● <groupId>net.juggenova.sample</groupId>● <version>1.1</version>● <relativePath>../parent</relativePath>
– </parent>● Useful
– if you have many similar projects/components– to separate responsibilities between senior and
junior developers – to encapsulate company-wide settings
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Issues and suggestions
● Main issue: children must reference parent version explicitely
– strong dependency! (as usual with inheritance)– there is no <version>LATEST</version> or <version>[1.0,)</version> for the parent
– if you change the parent, must update ALL children
● So, avoid putting in the parent things that change– your project modules versions– developer/machine-specific settings
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Suggestion
Separate things that change from things that stay the same
Bruce Eckel
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Dependency POMs
● Maven2 supports transitive dependencies
– controlled by a consistent use of the <scope> tag
● compile (default)– your libs
● test– junit, spring-test
● provided– servlet-api
● runtime– log4j
● system – tools.jar
minimize them!your POM library POM
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Issues and suggestions
● Good old encapsulation / minimize coupling– minimize dependencies– minimize visibility
● Can also define codeless POMs, which only contain a group of other dependencies
– declare with <packaging>pom</packaging>
– used with– <dependency>...
● <type>pom</type>– </dependency>
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Dependency Management
● Several libraries are often used in many modules● commons-logging, spring, servlet-api,...
– avoid repeating their version everywhere in POMs ● Apply DRY & separation of concerns
– which version to use in the parent/main POM● <dependencyManagement> (artifact, group, version)
– whether to use it ● <dependency> (artifact, group only) </dependency>
● Tip: <dependencyManagement> is also effective in overriding versions coming from transitive dependencies
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Aggregation
● Multimodule projects– every goal is repeated on
all modules by the reactor plugin– mvn clean– mvn compile
– modules can be children of master
● but not necessarily
<modules> <module>client</module> <module>server</module> <module>test</module></modules>
main POM module POM
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Issues and suggestions
● Issue: modules are referenced by folder name– beware when checking out or renaming
● Issue: IDE plugin support is not perfect– m2eclipse requires manual refresh of dependencies
after configuration changes● also, different classpaths in eclipse and maven when
opening a multimodule project as a single project– netbeans only supports separate modules
● Risk: pom proliferation (think of maintenance)– mvn modules vs SVN modules
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Suggestion
Common Reuse Principle
Package together what is used/reused togehter
Robert C. Martin
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Tip: create a “Master” POM
● A “component list” POM– does not have its own code or settings– just an index of all modules to be built– it is NOT the parent of the modules
● Example: the main spring pom which triggers the build of
– spring-core– spring-mvc– spring-test– ...
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Make it easy to create new projects
● Define an archetype – a customizable template for creating a kind of
projects (e.g. a web application)● defines POMs, project structure
● Simple setup with – mvn archetype:create-from-project
– customize with resource filtering ● ${property} references in the archetype
● Use http://appfuse.org – library of pre-assembled archetypes
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Part 3
Automate the entire build
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Automate the entire build
● Build means much more than compile!● Avoid manual steps!
– copy, rename, deploy to a test server...– pass configuration information
● Automatically process resources – copy and filter configuration files, CSS, HTML, properties
● Share resources across projects– package them as jar/zip– reuse them in a war project with jar/zip/war overlays
● http://maven.apache.org/plugins/maven-war-plugin/overlays.html
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Assembly plugin
● Creates zips/jars containing any kind of resource– project sources– common files
● XSDs● html/CSS● templates
– http://maven.apache.org/plugins/maven-assembly-plugin
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Preview and test webapps with the Jetty plugin
● Run a webapp directly from source folders– mvn jetty:run
● Advantages– very fast– resource changes are visible without restart– automatic redeploy after code changes– http://docs.codehaus.org/display/JETTY/Maven+Jetty+Plugin
● Now a mvn glassfish:run goal is also available– full JEE 5.0 support– https://maven-glassfish-plugin.dev.java.net/
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Automate deployment
● Deploy to an application server with cargo– can even download, install and run a full Jboss
instance for testing purposes– http://cargo.codehaus.org/
● Write custom ssh-based scripts using the ssh/scp ant tasks within the maven-antrun-plugin
– transfer files to test servers– launch administration scripts
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Integrate with the IDE
● E.g. Eclipse plugin (m2eclipse)– http://m2eclipse.sonatype.com
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Use a group repository
● Why your own?● Within a Team
– deploy and share your project artifacts● so that other developers do not have to rebuild them
– “mavenize” external jars which miss a POM– centrally configure and control which repositories
and artifacts are used– cache dependencies
● available when internet connection breaks● faster download times
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Sonatype Nexus repository
● Powerful web-based console– and REST API
● Lightweight● Easily upload artifacts via HTTP● Quickly search for jars
– with the included index
● Download from http://nexus.sonatype.org/– unzip and run!
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
settings.xml: Mirror definition
● Team repository in addition to central– <repository>
● <id> set </id>● <url> http://server:8080/repository </url>
– </repository>● Team repository as a mirror of central (or others)
– <mirror>● <id> central </id>● <url> http://server:8080/repository</url>● <mirrorOf> central </mirrorOf>
– </mirror>● Team repository as the only one
– <mirror>● <id> ... </id> <url> ... </url>● <mirrorOf> * </mirrorOf>
– </mirror>
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Part 4
Troubleshooting
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Build troubleshooting
● Verify POM structure– mvn validate
● Verify actually used dependencies – mvn dependency:tree
● -Dinclude=spring● Verify the full POM
– mvn help:effective-pom– m2eclipse plugin
● Moreover, – keep a consistent naming scheme to prevent typos
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Debug/Log
● Run mvn with– -e (print Exception stacktraces)– -X (print debug info)
● POM information can be accessed at runtime!– META-INF/<group>/<artifact>/pom.properties
● groupId● artifactId● version
– META-INF/../pom.xml ● full POM info
Resource[] resources = applicationContext .getResources("classpath*:META-INF/maven"+
"/**/pom.properties ");
for (Resource r : resources) { Properties p = new Properties (); p.load(r.getInputS tream());
artifact = p.getProperty("artifactId"); vers ion = p.getProperty("vers ion");
}
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Add a timestamp to your builds
● Automatically define a timestamp property– use it in resources or test properties
– <plugin>● <groupId>org.codehaus.mojo</groupId>● <artifactId>buildnumber-maven-plugin</artifactId>
● <executions> ... </executions>● <configuration>● <format>{0,date,yyyy-MM-dd HH:mm:ss}</format>● <items>● <item>timestamp</item>● </items>● </configuration>
</plugin>● http://mojo.codehaus.org/buildnumber-maven-plugin
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Part 5
Keep the build fast
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Keep the build fast
● Ideally, zero-time build– http://blog.carbonfive.com/2008/09/java/make-the-
things-you-do-often-fast-and-easy ● The more often a task is performed, the more its
optimization improves developer productivity– save time for actual project work
● Run maven on the latest JDK– benefit from JDK 1.6 fast startup times/optimizations
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Eclipse compiler
● Faster than JDK's javac– also provides more warnings (unused variables, generics
misuse...)– <plugin>– <artifactId>maven-compiler-plugin</artifactId>– <configuration>– <compilerId>eclipse</compilerId>– </configuration>– <dependencies>– <dependency>
● <groupId>org.codehaus.plexus</groupId>– <artifactId>plexus-compiler-eclipse</artifactId>– <version>1.5.2</version>– </dependency>– </dependencies>– </plugin>
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Unit test vs integration tests
● Run unit tests often– must not take half an hour! or else developers will
just skip them – -Dmaven.test.skip=true
● Separate unit tests from integration tests– unit tests in every project/module
● fast● run at every build (within mvn install)
– integration and acceptance tests in dedicated module
● run after major changes, and/or on build servers
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Remove useless build elements
● POM, plugin and dependency list keeps growing● Periodically review the POM
– Remove unused dependencies● copying them around means more slow disk accesses ● mvn dependency:analyze
– Remove unused plugins● move them to optionally-activated profiles
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Speed-up day-to-day tasks
● Define a default goal– <defaultGoal>compile</defaultGoal>
– then just run – mvn
● Use the right goal– avoid a full mvn install if you just need a mvn test
● Define shell aliases for common tasks● Use a CI server that reads and reuses mvn
configuration such as hudson– https://hudson.dev.java.net
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Incrementally build large multimodule projects
● Reactor plugin– http://maven.apache.org/plugins/maven-reactor-plugin/ – manages dependencies and build order
● resume a build from the last failed module– mvn reactor:resume
● build a project and all its dependencies– mvn reactor:make
● build all modules which have an SVN status of changed – mvn reactor:make-scm-changes
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
References
● Maven official site– http://maven.apache.org
● Best online book– Maven 2 – The Definitive Guide – http://books.sonatype.com/maven-book
● JavaWorld articles– Introduction to maven2
● http://www.javaworld.com/javaworld/jw-12-2005/jw-1205-maven.html– POM
● http://www.javaworld.com/javaworld/jw-05-2006/jw-0529-maven.html
Carlo Bonamico - [email protected] – JUG GenovaJavaday Roma III Edizione – 24 gennaio 2009
Thanks for your attention!
● Learn more at – http://www.carlobonamico.com/blog – http://juggenova.net
● presentations, demos, code samples● Play with the samples
– http://juggenova.net/code-samples/ ● Contact me at
– [email protected]● Related reading: Continuous Integration with Hudson
– http://www.slideshare.net/carlo.bonamico/continuous-integration-with-hudson