Maven 3 Tutorial – Project Setup

June 11th, 2011 by David Kessler Leave a reply »

Multiple Artifacts from a Single Source

Maven restricts projects to one artifact per ‘pom’ file. While we can argue whether this is the right approach, there is a simple solution. If you have a project called ‘sample-service’ that produces a WAR and you want to create a JAR from the same source code then you need to create a second package containing a single pom file.

|_sample-service
  |_src
  |_pom.xml
|_sample-client
  |_pom.xml

The ‘sample-client’ pom is configured to point to ‘sample-service’ for it’s source files. This should be added to the ‘build-helper-maven-plugin’ configuration. Please refer to http://mojo.codehaus.org/build-helper-maven-plugin/usage.html for more information.

<configuration> 
	<sources> 
		<source>**/src/main/java/**</source> 
		<source>**/src/main/resources/**</source> 
	</sources> 
</configuration>

Release Plugin

This is a very powerful plugin. If you’ve ever released a project by hand you will appreciate this plugin. One of my favorite features is that it checks to see if all of the dependencies refer to released versions. Without this automatic check you are forced to search through all of the dependency management configurations for unreleased dependencies. Depending on the size of your hierarchy this can be quite painful.

Along with this dependency check it also runs all of the tests, tags the code with the release name, and publishes the artifacts in the Maven repository. This plugin embodies the best standards for releasing within our industry. Standards that I easily forget and/or mess up. I highly recommend that you use this plugin to release your projects. Please refer to http://maven.apache.org/plugins/maven-release-plugin for more information.

Aggregate POM

An aggregate POM joins multiple modules together.

_pom.xml (aggregate)
  |_sample-service
    |_pom.xml (module 1)
  |_sample-client
    |_pom.xml (module 2)

The aggregate pom configures multiple modules in the modules section.

<project> 
	<modelVersion>4.0.0</modelVersion> 
	<groupId>com.mycompany.app</groupId> 
	<artifactId>sample-app</artifactId> 
	<version>1</version> 
	<packaging>pom</packaging> 
	<modules> 
		<module>sample-service</module> 
		<module>sample-client</module> 
	</modules> 
</project>

When you execute a Maven command at the aggregate level it will execute the same command on all of the configured modules. If any of these modules depends on another module Maven builds them in the correct order. This is a simple way to break up a large project into focused modules without loosing a coordinated project management strategy. While this could be replicated with Ant and Ivy it would be painful to configure and maintain. Aggregate projects are first class citizens in Maven.

Dependency Management

The ‘dependencymanagement’ section defines the acceptable versions for a project. This configuration does not result in a JAR being downloaded and included in the project. On the other hand, this is a directive specifying which version of a dependency should be used if a project depends on it. This is a simple way to force Maven to select a specific dependency version. In the case of an aggregate project it is best to add this to the aggregate pom. Configure the dependency versions in one place for all of the modules.

<dependencyManagement> 
	<dependencies> 
		<dependency> 
			<groupId>test</groupId> 
			<artifactId>a</artifactId> 
			<version>1.2</version> 
		</dependency> 
		<dependency> 
			<groupId>test</groupId> 
			<artifactId>b</artifactId> 
			<version>1.0</version> 
			<scope>compile</scope> 
		</dependency> 
		<dependency> 
			<groupId>test</groupId> 
			<artifactId>c</artifactId> 
			<version>1.0</version> 
			<scope>compile</scope> 
		</dependency> 
		<dependency> 
			<groupId>test</groupId> 
			<artifactId>d</artifactId> 
			<version>1.2</version> 
		</dependency> 
	</dependencies> 
</dependencyManagement>

Distribution Zip

Maven provides a simple way to package all of your artifacts in a single zip file. This simplifies the deployment process and increases traceability. For example I have used this feature to package my WAR, SQL, and external PDF files in the same zip file. Our deployment team extracted the WAR and PDF files and deployed them. Then they passed the SQL on to the DBA’s to run the scripts. All of the files necessary to deploy our project were packaged together and published to our Maven repository. Please refer to http://maven.apache.org/plugins/maven-assembly-plugin for more information.

Conclusions

Maven provides a holistic approach to project management. Maven provides standard conventions that can be easily modified and extended. When our development team switched from Ant/Ivy to Maven we spent less time focusing on how to build our projects. In the end Maven provided industry project management standards that we could depend on. Even when we spent hours trying to perfect our Ant build process we were getting some things wrong. We were focused on deploying the product at that moment. Unfortunately companies need to insure that deployments are traceable, dependable, and reproducible. Maven freed us up to focus on getting the product out while protecting our companies interests right out of the box.

Advertisement

35 comments

  1. Akrem Saed says:

    I always wanted to start using Maven along with Archiva for some time now, and this just helped me to jump start that … excellent post, thanks david

  2. mark says:

    acording to mvn -help it should be “mvn –version” instead of “mvn -version”

  3. mark says:

    I guess that’s a wordpress issue (- – instead of -)

  4. mark says:

    ‘eclipze.exe’ should be ‘eclipse.exe’. and thanks thanks thanks for the extremely helpful post

  5. David Kessler says:

    I fixed ‘eclipze.exe’. Nice catch. Thank you.

  6. David Kessler says:

    Both ‘mvn –version’ and ‘mvn -version’ work for me. I updated it to the latter. Thank you.

  7. greg says:

    correcting the corrector

    acording to mvn -help it should be “mvn –version” instead of “mvn -version”

  8. Akrem Saed says:

    one little issue I encountered was maven was not downloading dependencies from repository locations defined in a project pom.xml

    the pom had the following :
    <repositories>
    <repository>
    <id>springbyexample.org</id>
    <name>Spring by Example</name>
    <url>http://www.springbyexample.org/maven/repo</url&gt;
    </repository>

    <repository>
    <id>com.springsource.repository.bundles.release</id>
    <name>SpringSource Enterprise Bundle Repository – SpringSource Bundle Releases</name>
    <url>http://repository.springsource.com/maven/bundles/release</url&gt;
    </repository>
    <repository>
    <id>com.springsource.repository.bundles.external</id>
    <name>SpringSource Enterprise Bundle Repository – External Bundle Releases</name>
    <url>http://repository.springsource.com/maven/bundles/external</url&gt;
    </repository>
    <repository>
    <id>spring.maven.milestone</id>
    <name>Spring Milestone Maven Repo</name>
    <url>http://repository.springsource.com/maven/bundles/milestone</url&gt;
    </repository>

    <repository>
    <id>maven2-repository.dev.java.net</id>
    <name>Java.net Maven 2 Repository</name>
    <url>http://download.java.net/maven/2</url&gt;
    </repository>
    </repositories>

    but since I configured Archiva to ONLY mirror central maven2-repository.dev.java.net but in the maven settings.xml file we used
    <mirror>
    <id>archiva.default</id>
    <url>http://localhost:8095/archiva/repository/internal/</url&gt;
    <mirrorOf>*</mirrorOf>
    </mirror>

    the * was the problem because we are telling maven to always use archiva as the mirror , but Archiva is only mirroring two repositories . To fix this , we changed the last one to

    <mirror>
    <id>archiva.default</id>
    <url>http://localhost:8095/archiva/repository/internal/</url&gt;
    <mirrorOf>central,maven2-repository.dev.java.net</mirrorOf>
    </mirror>

  9. john says:

    Your screenshots are .bmp files. I just can’t believe it. Page 3 of this article nearly weights 100 MB. I’m glad you made this tutorial but, seriously, .bmp?

  10. David Kessler says:

    Good catch. I updated it with smaller .jpg files. Thank you.

  11. Andi says:

    after many days – with this tutorial maven run , thanks

  12. Apache Omega says:

    I’ve been trying for days to get maven running and it just wont work.
    I type in mvn -version and it says mvn is not recognized
    what the hell am i doing wrong?

  13. Travis Klotz says:

    Omega,

    It sounds like you do not have M2_HOME/bin on your Path. So when you try to execute the command, it had no idea where the program is.

    T

  14. Adel M says:

    Very nice overview of Maven! but please do something about the missing xml tags on the xml examples. Thanks!

  15. David Kessler says:

    Thank you. Nice catch. I’m not sure how the xml tags got stripped off of this post but I added them back.

  16. Alvi says:

    Hei,

    I follow the tutorial very well but when i run mvn install i got following error. Can some one tell me what i miss.. thanks

    [ERROR] Failed to execute goal org.apache.maven.plugins:maven-war-plugin:2.1.1:war (default-war) on project onlineweb: Error assembling WAR: webxml attribute i
    s required (or pre-existing WEB-INF/web.xml if executing in update mode) -> [Help 1]
    org.apache.maven.lifecycle.LifecycleExecutionException: Failed to execute goal org.apache.maven.plugins:maven-war-plugin:2.1.1:war (default-war) on project inmo
    bilweb: Error assembling WAR: webxml attribute is required (or pre-existing WEB-INF/web.xml if executing in update mode)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:217)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:153)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:145)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:84)
    at org.apache.maven.lifecycle.internal.LifecycleModuleBuilder.buildProject(LifecycleModuleBuilder.java:59)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.singleThreadedBuild(LifecycleStarter.java:183)
    at org.apache.maven.lifecycle.internal.LifecycleStarter.execute(LifecycleStarter.java:161)
    at org.apache.maven.DefaultMaven.doExecute(DefaultMaven.java:320)
    at org.apache.maven.DefaultMaven.execute(DefaultMaven.java:156)
    at org.apache.maven.cli.MavenCli.execute(MavenCli.java:537)
    at org.apache.maven.cli.MavenCli.doMain(MavenCli.java:196)
    at org.apache.maven.cli.MavenCli.main(MavenCli.java:141)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launchEnhanced(Launcher.java:290)
    at org.codehaus.plexus.classworlds.launcher.Launcher.launch(Launcher.java:230)
    at org.codehaus.plexus.classworlds.launcher.Launcher.mainWithExitCode(Launcher.java:409)
    at org.codehaus.plexus.classworlds.launcher.Launcher.main(Launcher.java:352)
    Caused by: org.apache.maven.plugin.MojoExecutionException: Error assembling WAR:
    webxml attribute is required (or pre-existing WEB-INF/web.xml if executing in update mode)
    at org.apache.maven.plugin.war.WarMojo.execute(WarMojo.java:175)
    at org.apache.maven.plugin.DefaultBuildPluginManager.executeMojo(DefaultBuildPluginManager.java:101)
    at org.apache.maven.lifecycle.internal.MojoExecutor.execute(MojoExecutor.java:209)
    … 19 more
    Caused by: org.codehaus.plexus.archiver.ArchiverException: webxml attribute is required (or pre-existing WEB-INF/web.xml if executing in update mode)
    at org.codehaus.plexus.archiver.war.WarArchiver.initZipOutputStream(WarArchiver.java:149)
    at org.codehaus.plexus.archiver.zip.AbstractZipArchiver.createArchiveMain(AbstractZipArchiver.java:346)
    at org.codehaus.plexus.archiver.zip.AbstractZipArchiver.execute(AbstractZipArchiver.java:250)
    at org.codehaus.plexus.archiver.AbstractArchiver.createArchive(AbstractArchiver.java:871)
    at org.apache.maven.archiver.MavenArchiver.createArchive(MavenArchiver.java:543)
    at org.apache.maven.plugin.war.WarMojo.performPackaging(WarMojo.java:225)
    at org.apache.maven.plugin.war.WarMojo.execute(WarMojo.java:159)
    … 21 more
    [ERROR]
    [ERROR] Re-run Maven using the -X switch to enable full debug logging.
    [ERROR]
    [ERROR] For more information about the errors and possible solutions, please read the following articles:
    [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/MojoExecutionException

  17. David Kessler says:

    I was able to reproduce this issue with the following steps.
    1. Create new Maven Project
    2. check ‘Create a simple project (skip archetype selection)
    3. next
    4. add groupId/artifactId
    5. change the packaging to ‘war’
    6. finish
    7. Run As -> Maven install

    The reason that you’re getting this message is that there isn’t a ‘web.xml’ file in ‘src/main/java/webapp/WEB-INF’

    You can either add a ‘web.xml’ file to this directory or you can use a Maven archetype. To use an archetype follow these steps.

    1. Create new Maven Project
    2. uncheck ‘Create a simple project (skip archetype selection)
    3. next
    4. select ‘All Catalogs’
    5. Filter = ‘maven-archetype-webapp’
    6. select ‘maven-archetype-webapp’
    7. next
    8. add groupId/artifactId
    9. finish

    This will create a ‘web.xml’ file for you.

    Hope this helps.

  18. Alvi says:

    Thanks David kessler now its work

  19. This post is great I’m glad I found it

  20. Tory Barren says:

    This is simply supurb, very indepth, thank you.

  21. Mara says:

    very good submit, i definitely love this website, carry on it

  22. Abdul Mannan Khan says:

    kudos.. Great tutorial for start-up.

  23. Vikas says:

    Great!!!! Above steps worked for me. Thanks.

  24. Jay Ungerland says:

    “Build Success!”

    Many, many thanks for this detailed and lucid tutorial.

  25. oussama smiai says:

    Your tutorial is very helpful, I wish I can find a tutorial about configuring settings.xml and M2_REPO variable

  26. vishu says:

    its very good…..

    thanks

  27. shamna says:

    Could you please help me how to create a login and registration page using maven??

  28. David Kessler says:

    Maven is not a web framework. You need to look into Spring MVC or Grails or some kind of web framework to create a login and registration page.

  29. when i am opening pom.xml,acoording to this ,i have select plug-in.but i am not geeting that option when i was open pom.xml.i am geeting window like Overview ……what i have to do ,to select plug-in

  30. saad says:

    thank so much

  31. baba khan says:

    very good tutorial.. and so helpfull

Leave a Reply

*