Author: Mitali Chaudhary & Rohit Singh
What is Maven?
Maven is a project management and comprehension tool that provides developers a complete build lifecycle framework. Development team can automate the project’s build infrastructure in almost no time as Maven uses a standard directory layout and a default build lifecycle.
Maven simplifies and standardizes the project build process. It handles compilation, distribution, documentation, team collaboration and other tasks seamlessly. Maven increases reusability and takes care of most of the build related tasks.
Maven Evolution
Maven was originally designed to simplify building processes in the Jakarta Turbine project. There were several projects and each project contained slightly different ANT build files. JARs were checked into CVS.
The Apache group then developed Maven which can build multiple projects together, publish project information, deploy projects, share JARs across several projects and help in collaboration of teams.
Objective
The primary goal of Maven is to provide developer with the following uses
A comprehensive model for projects, which is reusable, maintainable, and easier to comprehend.
Plugins or tools that interact with this declarative model.
What is the POM?
POM stands for “Project Object Model”. It is an XML representation of a Maven project held in a file named pom.xml.
The POM contains all necessary information about a project, as well as configurations of plugins to be used during the build process. It is the declarative manifestation of the “who”, “what”, and “where”, while the build lifecycle is the “when” and “how”
Maven Coordinates
The POM defined above is the bare minimum that Maven allows. groupId:artifactId:version are all required fields The three fields act much like an address and timestamp in one. This marks a specific place in a repository, acting like a coordinate system for Maven projects:
groupId: This is generally unique amongst an organization or a project. For example, all core Maven artifacts do (well, should) live under the groupId org.apache.maven. Group ID’s do not necessarily use the dot notation, for example, the junit project. Note that the dot- notated groupId does not have to correspond to the package structure that the project contains. It is, however, a good practice to follow. When stored within a repository, the group acts much like the Java packaging structure does in an operating system. The dots are replaced by OS specific directory separators (such as ‘/’ in Unix) which becomes a relative directory structure from the base repository. In the example given, the org.codehaus.mojo group lives within the directory $M2_REPO/org/codehaus/mojo.
artifactId: The artifactId is generally the name that the project is known by. Although the groupId is important, people within the group will rarely mention the groupId in discussion (they are often all be the same ID, such as the MojoHaus project groupId: org.codehaus.mojo). It, along with the groupId, creates a key that separates this project from every other project in the world (at least, it should 🙂 ). Along with the groupId, the artifactId fully defines the artifact’s living quarters within the repository. In the case of the above project, my-project lives in $M2_REPO/org/codehaus/mojo/my-project.
version: This is the last piece of the naming puzzle. groupId:artifactId denotes a single project but they cannot delineate which incarnation of that project we are talking about. Do we want the junit:junit of 2018 (version 4.12), or of 2007 (version 3.8.2)? In short: code changes, those changes should be versioned, and this element keeps those versions in line. It is also used within an artifact’s repository to separate versions from each other. my- project version 1.0 files live in the directory structure $M2_REPO/org/codehaus/mojo/my- project/1.0.
The three elements given above point to a specific version of a project, letting Maven know who we are dealing with, and when in its software lifecycle we want them.
Packaging
The Super POM
Similar to the inheritance of objects in object oriented programming, POMs that extend a parent POM inherit certain values from that parent. Moreover, just as Java objects ultimately inherit from java.lang. Object, all Project Object Models inherit from a base Super POM.
You can take a look at how the Super POM affects your Project Object Model by creating a minimal pom.xml and executing on the command line: mvn help: effective- pom
One main advantage of the POM hierarchy in Maven is that we can extend and override the configuration inherited from the top. Therefore, to override the configuration of a given element or an artifact in the POM hierarchy, Maven should be able to uniquely identify the corresponding artifact.
Effective POM
Effective POM combines all the default settings from the super POM file and the configuration defined in our application POM. Maven uses default values for configuration elements when they are not overridden in the application pom.xml. Hence, if we take the same sample POM file from the simplest POM section, we’ll see that the effective POM file will be the merge between simplest and super POM. We can visualize it from the command line:
Convention over Configuration
Maven uses Convention over Configuration, which means developers are not required to create build process themselves.
Developers do not have to mention each and every configuration detail. Maven provides sensible default behavior for projects. When a Maven project is created, Maven creates default project structure. Developer is only required to place files accordingly and he/she need not to define any configuration in pom.xml.
Maven Lifecycle:
The following lists all build phases of the default, clean and site lifecycles, which are executed in the order given up to the point of the one specified.
Clean Lifecycle:
Default Lifecycle:
Below is a representation of the default Maven lifecycle and its 8 steps: Validate, Compile, Test, Package, Integration test, Verify, Install and Deploy.
Maven lifecycle by default consists of 8 major steps or phases for compiling, testing, building and installing a given project as specified below:
Validate: This step validates if the project structure is correct. For example — It checks if all the dependencies have been downloaded and are available in the local repository.
Compile: It compiles the source code, converts the .java files to .class and stores the classes in target/classes folder.
Test: It runs unit tests for the project.
Package: This step packages the compiled code in distributable format like JAR or WAR. Integration test: It runs the integration tests for the project.
Verify: This step runs checks to verify that the project is valid and meets the quality standards.
Install: This step installs the packaged code to the local Maven repository.
Deploy: It copies the packaged code to the remote repository for sharing it with other developers.
Note:Maven follows a sequential order to execute the commands where if you run step n, all steps preceding it (Step 1 to n-1) are also executed. For example — if we run the Installation step (Step 7), it will validate, compile, package and verify the project along with running unit and integration tests (Step 1 to 6) before installing the built package to the local repository.
Maven Commands:
mvn clean: Cleans the project and removes all files generated by the previous build. mvn compile: Compiles source code of the project.
mvn test-compile: Compiles the test source code. mvn test: Runs tests for the project.
mvn package: Creates JAR or WAR file for the project to convert it into a distributable format.
mvn install: Deploys the packaged JAR/ WAR file to the local repository.
mvn deploy: Copies the packaged JAR/ WAR file to the remote repository after compiling, running tests and building the project.
Maven also have Site lifecycle but we rarely use it while working with mule projects .This lifecycle
Generally when we run any of the above commands, we add the mvn clean step so that the target folder generated from the previous build is removed before running a newer build. This is how the command would look on integrating the clean step with install phase: mvn clean install
Similarly, if we want to run the step in debug mode for more detailed build information and logs, we will add -X to the actual command. Hence, the install step with debug mode on will have the following command: mvn -X install
Consider a scenario where we do not want to run the tests while packaging or installing the Java project. In this case, we use -DskipTests along with the actual command. If we need to run the install step by skipping the tests associated with the project, the command would be: mvn install -DskipTests
The settings.xml File in Maven
Maven provides a settings file, settings.xml, which allows us to specify which local and remote repositories it will use. We can also use it to store settings that we don’t want in our source code, such as credentials.
There are two locations where a settings.xml file may live:
1. The Maven install: ${maven.home}/conf/settings.xml
2. A user’s install: ${user.home}/.m2/settings.xml
Here is an overview of the top elements under settings:
The contents of the settings.xml can be interpolated using the following expressions:
${user.home} and all other system properties (since Maven 3.0)
${env.HOME} etc. for environment variables
Note that properties defined in profiles within the settings.xml cannot be used for interpolation.
Maven Archetype
It’s a project template from which other projects are created.
The main benefit of using archetypes is to standardize project development and to enable developers to easily follow best practices while bootstrapping their projects faster.
Create Archetype
Instead of manually creating the directory structure needed for an archetype, simply use mvn archetype:generate
-DgroupId=[your project’s group id]
-DartifactId=[your project’s artifact id]
-DarchetypeGroupId=org.apache.maven.archetypes
-DarchetypeArtifactId=maven-archetype-archetype
Afterwhich, you can now customize the contents of the archetype-resources directory, and archetype-metadata.xml, then, follow below step
Install the archetype and run the archetype plugin Install the archetype
Now that you have created an archetype, you can try it on your local system by using the following command. In this command, you need to specify the full information about the archetype you want to use (its groupId, its artifactId, its version) and the information about the new project you want to create (artifactId and groupId). Don’t forget to include the version of your archetype (if you don’t include the version, you archetype creation may fail with a message that version:RELEASE was not found)
Once you are happy with the state of your archetype, you can deploy (or submit it to Maven Central) it as any other artifact and the archetype will then be available to any user of Maven.
Originally published at https://apisero.com on June 7, 2022.