lunes, marzo 21, 2011

Que Rabia Que Ternura Ser El Sol Y La Luna Esto Es Una Locura Lo Que Siento Mujer

From Wikipedia "Maven is a software tool for project management and build automation.". Most of us in our projects are using Maven as a build tool. As you probably know, the main file in Maven is POM (Project Object Model).  POM file provides all configuration for a single project, like name, dependencies, plugins to be used, ... In large projects, you divide your project in several subprojects, each one with its POM. In this case it is a good practice to create a root POM through which one can compile all the modules with a single command. Also a parent POM can be defined for common plugins or configurations.
After this brief Maven introduction I expose a recurrent problem that I had with Maven. The problem is that in each project I started, I made a copy paste of POM files from my previous project to the new one. After some copy paste projects, I decided to create three templates, one for parent POM, another for project/subprojects, and one settings.xml that although this file is computer dependent, some configuration like repository server username/password and plugins repository are specified for all computers.
In both files I have defined next sections:
  • Information about project.
  • Distribution Server for uploading/downloading Artifacts.
  • Some reports for assuring quality.
  • SCM configuration for some Source Control Managers.
  • Two profiles.
  • Definition of useful Maven plugins.
settings file settings.xml file contains elements used for defining Maven configuration.

I define:

  • tag <localrepository> an alternative directory for storing local artifacts rather than home directory. I really don't like use my home directory as local repository, because my personal documents are mixed with dependencies.
  • tag <servers> for specifying login and password for snapshot and release repository server. I use Nexus Repository Manager for uploading/downloading artifacts, and is common that each developer has its authentication data.
  • tag <pluginrepository> where I inform Maven where it can download plugins. In my case Nexus Repository, but an external repository can also be used. This information is present in settings.xml because you can run Maven without any project created previously (when start a project with archetypes). And in this case Maven will use settings.xml for finding where plugins should be downloaded.
superPOM file POMs that extend a parent POM inherit certain values from that parent. This is useful for defining typical values that are shared across all projects. Moreover a parentPOM should acts as aggregation POM too, because of aggregation, one can release all subprojects simply goaling this file. I define:
  • tag <packaging> must be pom.
  • tag <properties> defines servers location.
  • tag <build> defining directory locations for classes, resources, test classes, ... Although it is the default Maven configuration, I prefer having always present in POM files so no misunderstanding can occurs.
  • tag <plugins> I define 3 plugins: maven-compiler-plugin that should only compile with version 1.6, maven-deploy-plugin for deploying project, and versions-maven-plugin for managing project/dependencies versions.
  • tag <reporting> only one reporting is executed in each execution, and this is maven-surefire-report-plugin used for reporting why a JUnit test has failed.
  • tag <profiles> defines two profiles. One called source-javadoc that generates a zip file with project source files, and an archive with project javadoc too. Can be executed with option -Psource-javadoc. The other profile is called metrics. This profile executes report plugins for creating reports about Source Quality. Because it is an expensive process, I define them in a different profile rather than default, so in my Continuous Integration System, does not executed every night but once per week. Plugins are: maven-site-plugin, cobertura-maven-plugin, maven-checkstyle-plugin, maven-pmd-plugin and findbugs-maven-plugin.
  • tag <dependencies> I define common dependencies across all projects. As you can imagine, these dependencies are about testing, so JUnit is defined for testing, Mockito for mocking and Hamcrest.
  • tag <repositories> defines repositories where artifacts will be uploaded/downloaded. It is a good practice to have a central artifact repository in your company divided between Snapshots and Release jars. In our case Nexus Repository Manager is used. Tag <id> inside is used in settings.xml for specifying login and password of identified server.
templatePOM file
Template POM is standard POM for all projects/subprojects. In this POM you will define specific configuration of each project, like name, version, ... and this POM is which inherits superPOM but also superPOM aggregates it using <module> tag.
In this file should be configured the groupId and artifactId with project specific configuration. 
Download templatePOM.xml

These three files are available here, feel free to download, use, and modify them. If you have any suggestion, it would be a pleasure to watch and adding to that files.

3 comentarios:

Mirko dijo...


I like to define as well to provide standard versions for dependencies. So individual projects do not need to define versions.


Alex dijo...

Thank you Mirko for your comment, but in my case this is difficult because one day I am developing a project using iBatis, and the other one Hibernate. For that reason simply I just don't want to create dependencies in parent pom. Anyway what you tell us is so interesting.

Thank you very much,

ehsavoie dijo...

Why not use Maven archetype ?
This is the best way as the user can configure exactly the project when creating it for example using the artifactId in the scm url etc.

What Mirko is talking about is dependencyManagement (providing a default version for dependencies thus eliminating the risk of incoherence in dependency version between projects)