The conventions over configuration principle are what makes maven so popular. Maven stores default configurations in a super pom
and the project pom
overrides these configurations. The commands you run in your project like mvn clean install
are nothing but build lifecycle
. This part of the tutorial will cover maven build lifecycle, types of pom, effective pom and etc.
Types of POM – Project Object Model
Will make use of the code created in the Spark-app from the previous article. There are basically 3 types of POM – Project pom, Super pom, Effective pom.
1. Project Pom
As the name suggests, this is the pom that is present in your project’s root. This is the place that holds information about your project, dependencies, plugins etc. spark-api-example\pom.xml
is the project pom.
2. Super Pom
Like I keep saying, maven follows conventions over configurations. Technically, a project pom inherits configuration and properties from the default maven pom known as Super Pom. Refer the official site for more information.
<project> <modelVersion>4.0.0</modelVersion> <repositories> <repository> <id>central</id> <name>Central Repository</name> <url>https://repo.maven.apache.org/maven2</url> <layout>default</layout> <snapshots> <enabled>false</enabled> </snapshots> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>central</id> <name>Central Repository</name> <url>https://repo.maven.apache.org/maven2</url> <layout>default</layout> <snapshots> <enabled>false</enabled> </snapshots> <releases> <updatePolicy>never</updatePolicy> </releases> </pluginRepository> </pluginRepositories> <build> <directory>${project.basedir}/target</directory> <outputDirectory>${project.build.directory}/classes</outputDirectory> <finalName>${project.artifactId}-${project.version}</finalName> <testOutputDirectory>${project.build.directory}/test-classes</testOutputDirectory> <sourceDirectory>${project.basedir}/src/main/java</sourceDirectory> <scriptSourceDirectory>${project.basedir}/src/main/scripts</scriptSourceDirectory> <testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory> <resources> <resource> <directory>${project.basedir}/src/main/resources</directory> </resource> </resources> <testResources> <testResource> <directory>${project.basedir}/src/test/resources</directory> </testResource> </testResources> <pluginManagement> <!-- NOTE: These plugins will be removed from future versions of the super POM --> <!-- They are kept for the moment as they are very unlikely to conflict with lifecycle mappings (MNG-4453) --> <plugins> <plugin> <artifactId>maven-antrun-plugin</artifactId> <version>1.3</version> </plugin> <plugin> <artifactId>maven-assembly-plugin</artifactId> <version>2.2-beta-5</version> </plugin> <plugin> <artifactId>maven-dependency-plugin</artifactId> <version>2.8</version> </plugin> <plugin> <artifactId>maven-release-plugin</artifactId> <version>2.5.3</version> </plugin> </plugins> </pluginManagement> </build> <reporting> <outputDirectory>${project.build.directory}/site</outputDirectory> </reporting> <profiles> <!-- NOTE: The release profile will be removed from future versions of the super POM --> <profile> <id>release-profile</id> <activation> <property> <name>performRelease</name> <value>true</value> </property> </activation> <build> <plugins> <plugin> <inherited>true</inherited> <artifactId>maven-source-plugin</artifactId> <executions> <execution> <id>attach-sources</id> <goals> <goal>jar-no-fork</goal> </goals> </execution> </executions> </plugin> <plugin> <inherited>true</inherited> <artifactId>maven-javadoc-plugin</artifactId> <executions> <execution> <id>attach-javadocs</id> <goals> <goal>jar</goal> </goals> </execution> </executions> </plugin> <plugin> <inherited>true</inherited> <artifactId>maven-deploy-plugin</artifactId> <configuration> <updateReleaseInfo>true</updateReleaseInfo> </configuration> </plugin> </plugins> </build> </profile> </profiles> </project>
3. Effective Pom
The effective-pom is the visible POM that results from the application of interpolation, inheritance and active profiles between project-pom and super pom.
Use the command below to see effective-pom, run it inside .\spark-api-example\
and see the result. IDEs like STS and IntelliJ can generate this for you.
mvn help:effective-pom
<?xml version="1.0"?> <project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> <modelVersion>4.0.0</modelVersion> <groupId>com.jstobigdata.maventutorial</groupId> <artifactId>spark-api-example</artifactId> <version>1.0-SNAPSHOT</version> <name>spark-api-example</name> <url>http://maven.apache.org</url> <properties> <maven.compiler.source>1.8</maven.compiler.source> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <maven.compiler.target>1.8</maven.compiler.target> </properties> <dependencies> <dependency> <groupId>com.sparkjava</groupId> <artifactId>spark-core</artifactId> <version>2.8.0</version> <scope>compile</scope> </dependency> <dependency> <groupId>com.fasterxml.jackson.core</groupId> <artifactId>jackson-databind</artifactId> <version>2.8.8.1</version> <scope>compile</scope> </dependency> <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.2.2</version> <scope>compile</scope> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> </dependencies> <repositories> <repository> <id>repo.backbase.com</id> <url>https://repo.backbase.com/repo/</url> </repository> <repository> <snapshots> <enabled>false</enabled> </snapshots> <id>central</id> <name>Central Repository</name> <url>https://repo.maven.apache.org/maven2</url> </repository> </repositories> <pluginRepositories> <pluginRepository> <id>repo.backbase.com</id> <url>https://repo.backbase.com/repo/</url> </pluginRepository> <pluginRepository> <releases> <updatePolicy>never</updatePolicy> </releases> <snapshots> <enabled>false</enabled> </snapshots> <id>central</id> <name>Central Repository</name> <url>https://repo.maven.apache.org/maven2</url> </pluginRepository> </pluginRepositories> <build> <sourceDirectory>/Users/bikramkundu/jstobigdata/awesome-maven-examples/spark-api-example/src/main/java</sourceDirectory> <scriptSourceDirectory>/Users/bikramkundu/jstobigdata/awesome-maven-examples/spark-api-example/src/main/scripts</scriptSourceDirectory> <testSourceDirectory>/Users/bikramkundu/jstobigdata/awesome-maven-examples/spark-api-example/src/test/java</testSourceDirectory> <outputDirectory>/Users/bikramkundu/jstobigdata/awesome-maven-examples/spark-api-example/target/classes</outputDirectory> <testOutputDirectory>/Users/bikramkundu/jstobigdata/awesome-maven-examples/spark-api-example/target/test-classes</testOutputDirectory> <resources> <resource> <directory>/Users/bikramkundu/jstobigdata/awesome-maven-examples/spark-api-example/src/main/resources</directory> </resource> </resources> <testResources> <testResource> <directory>/Users/bikramkundu/jstobigdata/awesome-maven-examples/spark-api-example/src/test/resources</directory> </testResource> </testResources> <directory>/Users/bikramkundu/jstobigdata/awesome-maven-examples/spark-api-example/target</directory> <finalName>spark-api-example-1.0-SNAPSHOT</finalName> <pluginManagement> <plugins> <plugin> <artifactId>maven-antrun-plugin</artifactId> <version>1.3</version> </plugin> <plugin> <artifactId>maven-assembly-plugin</artifactId> <version>2.2-beta-5</version> </plugin> <plugin> <artifactId>maven-dependency-plugin</artifactId> <version>2.8</version> </plugin> <plugin> <artifactId>maven-release-plugin</artifactId> <version>2.5.3</version> </plugin> </plugins> </pluginManagement> <plugins> <plugin> <artifactId>maven-compiler-plugin</artifactId> <version>3.8.1</version> <executions> <execution> <id>default-compile</id> <phase>compile</phase> <goals> <goal>compile</goal> </goals> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </execution> <execution> <id>default-testCompile</id> <phase>test-compile</phase> <goals> <goal>testCompile</goal> </goals> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </execution> </executions> <configuration> <source>1.8</source> <target>1.8</target> </configuration> </plugin> <plugin> <artifactId>maven-clean-plugin</artifactId> <version>2.5</version> <executions> <execution> <id>default-clean</id> <phase>clean</phase> <goals> <goal>clean</goal> </goals> </execution> </executions> </plugin> <plugin> <artifactId>maven-resources-plugin</artifactId> <version>2.6</version> <executions> <execution> <id>default-testResources</id> <phase>process-test-resources</phase> <goals> <goal>testResources</goal> </goals> </execution> <execution> <id>default-resources</id> <phase>process-resources</phase> <goals> <goal>resources</goal> </goals> </execution> </executions> </plugin> <plugin> <artifactId>maven-jar-plugin</artifactId> <version>2.4</version> <executions> <execution> <id>default-jar</id> <phase>package</phase> <goals> <goal>jar</goal> </goals> </execution> </executions> </plugin> <plugin> <artifactId>maven-surefire-plugin</artifactId> <version>2.12.4</version> <executions> <execution> <id>default-test</id> <phase>test</phase> <goals> <goal>test</goal> </goals> </execution> </executions> </plugin> <plugin> <artifactId>maven-install-plugin</artifactId> <version>2.4</version> <executions> <execution> <id>default-install</id> <phase>install</phase> <goals> <goal>install</goal> </goals> </execution> </executions> </plugin> <plugin> <artifactId>maven-deploy-plugin</artifactId> <version>2.7</version> <executions> <execution> <id>default-deploy</id> <phase>deploy</phase> <goals> <goal>deploy</goal> </goals> </execution> </executions> </plugin> <plugin> <artifactId>maven-site-plugin</artifactId> <version>3.3</version> <executions> <execution> <id>default-site</id> <phase>site</phase> <goals> <goal>site</goal> </goals> <configuration> <outputDirectory>/Users/bikramkundu/jstobigdata/awesome-maven-examples/spark-api-example/target/site</outputDirectory> <reportPlugins> <reportPlugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-project-info-reports-plugin</artifactId> </reportPlugin> </reportPlugins> </configuration> </execution> <execution> <id>default-deploy</id> <phase>site-deploy</phase> <goals> <goal>deploy</goal> </goals> <configuration> <outputDirectory>/Users/bikramkundu/jstobigdata/awesome-maven-examples/spark-api-example/target/site</outputDirectory> <reportPlugins> <reportPlugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-project-info-reports-plugin</artifactId> </reportPlugin> </reportPlugins> </configuration> </execution> </executions> <configuration> <outputDirectory>/Users/bikramkundu/jstobigdata/awesome-maven-examples/spark-api-example/target/site</outputDirectory> <reportPlugins> <reportPlugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-project-info-reports-plugin</artifactId> </reportPlugin> </reportPlugins> </configuration> </plugin> </plugins> </build> <reporting> <outputDirectory>/Users/bikramkundu/jstobigdata/awesome-maven-examples/spark-api-example/target/site</outputDirectory> </reporting> </project>
Effective pom is needed to remove the guess works and debug real problems.
Build lifecycle, phases and goals in maven
Maven is built on the concept of build lifecycle, which means the process of building and distributing artifact is clearly defined. As a developer, you only need to learn a set of commands, that’s it!
There are 3 built-in build lifecycles: clean
, default
, and site
. The default
lifecycle handles project deployment, the clean lifecycle
handles project cleaning, while the site
lifecycle handles the creation of project’s site documentation.
In Maven, each build lifecycle has several phases. Each phase is a sequence of goals. Phases executes sequentially, executing a phase means executes all previous phases.
1. Clean Lifecycle (mvn clean
)
Running mvn clean
invokes clean lifecycle, and it has 3 phases. Use the same project from spark-application and try to run the same command.
- pre-clean – Perform custom action before deleting the
${basedir}/target
. - clean – Deletes
${basedir}/target
directory. - post-clean – Perform custom action after deleting
${basedir}/target
.
A specific phase can also be executed, e.g. mvn clean:clean
.
maven-clean-plugin
is the one that is responsible for mvn clean
lifecycle. You can include this in your project and assign custom tasks to these phases.
... <plugin> <artifactId>maven-clean-plugin</artifactId> <version>2.5</version> <executions> <execution> <id>default-clean</id> <phase>clean</phase> <goals> <goal>clean</goal> </goals> </execution> </executions> </plugin>
2. Default Lifecycle (mvn clean install
)
This is the default lifecycle commands that every developer has to know. The first phase is validate
and the last phase is deploy
. The common commands every developer has to know are listed below.
validate
– validate the project is correct and all necessary information is available.compile
– compile the source code of the project.test
– test the compiled source code using a suitable unit testing framework. These tests should not require the code to be packaged or deployed.package
– take the compiled code and package it in its distributable format, such as a.jar
,.war
, etc.verify
– run any checks on results of integration tests to ensure quality criteria are met.install
– install the package into the local repository, for use as a dependency in other projects locallydeploy
– done in the build-environment, copies the final package to the remote repository for sharing with other developers and projects.
There are some more commands which can be found from the official site. Take a look at the effective pom again to understand the plugins responsible for each of these commands.
3. Site Lifecycle (mvn site
)
As you learned in Introduction, Maven does more than building software artifacts from a project, it can also generate project documentation and reports about the project, or a collection of projects.
Project documentation and site generation have a dedicated lifecycle which contains 4 phases:
pre-site
–site
–post-site
–site-deploy
–
Try running mvn site
under the spark app and see what is happening.
What are maven goals?
In maven, Lifecycle is a sequence of named phases. Phases execute sequentially. Executing a phase means executes all previous phases.
A plugin is a collection of goals also called MOJO (Maven Old Java Object).
A plugin is like a class and goals are methods within the class.
When we run a phase – all goals bound to this phase are executed in order. Here are some of the phases and default goals bound to them:
compiler:compile
– thecompile
goal from the compiler plugin is bound to the compile phase.compiler:testCompile
is bound to the test-compile phase.surefire:test
is bound to test phase.install:install
is bound to install phase.jar:jar
andwar:war
is bound to package phase
Use the command below to know the goals bound to a phase and plugins
mvn help:describe -Dcmd=PHASE_NAME
mvn help:describe -Dcmd=install
You can find the complete list of default plugins:goal on the maven official site
Always make a point to take a look at the effective pom to understand the project more in details. I also encourage you to try out various lifecycle commands mentioned above.