The Project Object Model
Everything starts with the project object model (POM). The POM is defined in a pom.xml file that contains all the information necessary to build the project, generate reports and configure plugins. Maven supports the notion of a single artifact per project. This artifact may be a JAR, WAR, EAR, POM (just a pom.xml file) or some other special artifact. Listing One contains the pom.xml for the SudokuSolver module of the sample application. I provide very little information: parent, packaging (JAR), and dependencies. How can Maven build a project with so little information? The secret is in the standard directory layout + build lifecycle. Maven assumes various resources such as test code are located in a certain place and does the right thing about it (for example, compile the test code and run the unit tests).
<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> <parent> <groupId>GigiZone</groupId> <artifactId>Sudoku</artifactId> <version>1.0-SNAPSHOT</version> </parent> <artifactId>SudokuSolver</artifactId> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> </project>
Maven stores project artifacts and third-party dependencies in repositories. Artifacts are identified by group id, artifact id, and version. For example, the jar file spring-core-1.2.6.jar is identified by group id: org.springframework artifact, id: spring-code and version: 1.2.6. It is stored in the repository at <repository root>/org/springframework/spring-core/1.2.6. Each element in the fully qualified artifact id gets its own sub-directory. A project that depends on other project's artifacts finds them in the repository (or rather Maven finds them and makes them available at the right time). Artifacts are typically jar files, but can also be war and ear files as well as pom.xml files. There are three types of repositories: The local repository on the developer machine, shared internal repositories (corporate repository), and public repositories. All repositories are basically directories with a certain structure.
Dependency management is one of the stickiest issues in software development. It's difficult to get it right and it's difficult to keep it right. It helps to have Maven around. Maven 2 resolves dependencies transitively. If A depends on B and B depends on C then you need both B and C in order to use A. However, A only needs to specify its direct dependencies (B in this case). Maven determines that C is also necessary and make it available. Maven executes multi-module builds in the right order building dependencies and installing them into the local repository before building the modules that depend on them. Also if later B is modified such that it needs D also then the POM of A doesn't need to change. This is a nice encapsulation where A just states it depends on B and it is not affected by implementation changes in B. Dependencies in Maven 2 have scope. The scope concept recognizes various dependencies are needed only in certain times during the development/deployment cycle. The best example is junit, which is necessary during test time only. It is not required to build your project and it is not required at deployment time. There are five scopes:
- Compile scope means the dependency is necessary to build your project.
- Test scope means the dependency is necessary to test your project.
- Provided means the dependency is necessary at runtime but will be provided by the container (Servlet and JSP APIs are provided by Tomcat, for instance).
- Runtime and System are esoteric scopes and I couldn't figure out a proper use case for them. The Maven documentation is pretty sketchy about it.
Plugins are Maven's middle name. The core engine runs plugins to perform its duties. Each and every build phase is executed by plugins. They are also the one true way to extend and customize Maven. A plugin is basically a set of goals, a.k.a. MOJOs (Maven Old Java Objects) that are bound to a specific lifecycle phase. Maven executes the appropriate mojo for each phase in the build lifecycle as it chugs along the build. The mojos get their input from the POM.
Who Needs Maven?
Anyone who works on a project with more than a couple of modules and more than one developer would benefit from Maven. Even if you work alone on a small project, Maven can help clean up your build act.
I am a great admirer of standards for arbitrary things. Think about curly braces, indentation, and whitespace in most languages. Who cares, right? Still lots of people have to read other people's code in unfamiliar style, or write in a style they don't like due to coding guidelines (not to mention the time and arguments to write the coding guidelines document). Maven dictates a standard directory layout, standard build lifecycle, and standard goal names. It cancels at least one huge 4 hours project meeting where everybody argues if source files should be placed under "src" or "sources" and if the output directory should be called "build", "Build", or "output". The motto of Maven is "There is one way to do it". You can have your way (and eat it too) if must, but it will cost you (in simplicity).
Maven prevents artifact and third-party dependencies duplication by storing them in the repository. This saves space and time especially if the alternative is to store all the duplicates in your SCM system. The resources in the repository should never be stored in your SCM because your build artifacts are generated from your source code (which you do store in SCM I should hope) and the third-party dependencies are never changed (and if they do then the filename is changed too to reflect it) so there is no point in storing them in a versioning system.
The project management features of Maven are its extensive support for reports, site creation, and integration with continuos integration systems. If you manage a multi-developer large-scale project, you definitely need these features.