530 likes | 733 Views
Using Maven2. Free Maven Books. Maven: The Definitive Guide (alpha) www.sonatype.com/book. Better Builds with Maven www.mergere.com. The Maven Site. http://maven.apache.org/. What is Maven?. Build lifecycle Dependency management tool Artifact repository Collection of plugins
E N D
Free Maven Books Maven: The Definitive Guide (alpha) www.sonatype.com/book Better Builds with Maven www.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 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:eclipseand import with Eclipse, or create the project in Eclipse and add the Maven2 project nature
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.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:goale.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!
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>
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.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> </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
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 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 Listed at: http://maven.apache.org/plugins/ clean compiler deploy install resources site surefire verifier ear ejb jar rar war changelog changes checkstyle clover doap docck javadoc jxr pmd project-info-reports surefire-report ant antlr antrun archetype assembly dependency enforcer gpg help invoker one plugin release remote-resources repository scm source eclipse idea Codehaus: build-helper castor javacc jdepend native sql taglist Other: cargo jaxme jetty 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
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, deploysproject, 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
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)