As we saw in the previous chapter, each Maven project is described by an XML configuration file called Project Object Model. What we have yet to see is how Maven will use the information contained in the POM, how we can clean and build our projects, which tasks we can decide to run, and finally, how Maven plugins take part in the build process. In order to answer all these questions, we'll dive into the core concepts of Maven, which are as follows:
Using all these features, you will learn how to set up and build a complex multimodule Java EE application. All the examples of this chapter refer to a direct usage of the Maven tool from the command line; in Appendix B, Maven Integration for Eclipse we will show you how to manage a Maven project from Eclipse IDE.
A lifecycle is a sequence of phases. In each phase, depending on the POM configuration, one or more tasks are executed. These tasks are called goals. Despite the enormous variety of work that can be accomplished by Maven, there are only three built-in Maven lifecycles: default, clean, and site.
The default lifecycle is responsible for the build process, so it's the most interesting. Among its phases, the most important phases are described in the following table:
We'll speak later about local and remote Maven repositories.
When we invoke one phase from the command line, Maven executes all the phases of the lifecycle from the beginning up to the specified phase (included). In fact, one of the most common ways to run Maven is just to use the following syntax:
$ mvn <phase>
It will run all the portions of the respective lifecycle, ending with this phase.
Let's consider an example. Suppose that the POM file of our transportation-acq-ejb
module is the following, and it is located in the /transportation-project/transportation-acq-ejb
directory:
<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/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>com.packt.examples</groupId> <artifactId>transportation-project</artifactId> <version>0.0.1-SNAPSHOT</version> </parent> <artifactId>transportation-acq-ejb</artifactId> <packaging>jar</packaging> <name>transportation-acq-ejb</name> <dependencies> <dependency> <groupId>javax</groupId> <artifactId>javaee-api</artifactId> <version>6.0</version> <scope>provided</scope> </dependency> </dependencies> </project>
As we can see in the preceding code, the transportation-acq-ejb
module's parent is the transportation-project
parent project. We can add some sample Java classes and interfaces in the transportation-acq-ejb
project. First, we add an EJB local interface, MyEjb.java
:
package com.packt.samples; import javax.ejb.Local; @Local public interface MyEjb { public int myMethod(); }
Then, we add a dummy implementation, MyEjbImpl.java
:
package com.packt.samples; import javax.ejb.Stateless; @Stateless public class MyEjbImpl implements MyEjb { @Override public int myMethod() { return 0; } }
Finally, we add a unit test class, SampleTest.java
:
package com.packt.samples; import static org.junit.Assert.*; import org.junit.Test; public class SampleTest { @Test public void test() { assertTrue(true); } }
The directory structure of the transportation-acq-ejb
module is as shown in the following screenshot:
Execute the following command:
$ mvn install
We'll see the following output after executing the preceding command:
[INFO] Scanning for projects... [...] [INFO] ----------------------------------------------------------- [INFO] Building transportation-acq-ejb 0.0.1-SNAPSHOT [INFO] [INFO] --- maven-resources-plugin:2.6:resources (default-resources) @ transportation-acq-ejb --- […] [INFO] --- maven-compiler-plugin:2.5.1:compile (default-compile) @ transportation-acq-ejb --- [INFO] Compiling 2 source files to ~/transportation-project/transportation-acq-ejb/target/classes [INFO] [INFO] --- maven-resources-plugin:2.6:testResources (default-testResources) @ transportation-acq-ejb --- […] [INFO] --- maven-compiler-plugin:2.5.1:testCompile (default-testCompile) @ transportation-acq-ejb --- [INFO] Compiling 1 source file to ~/transportation-project/transportation-acq-ejb/target/test-classes [INFO] [INFO] --- maven-surefire-plugin:2.17:test (default-test) @ transportation-acq-ejb --- [INFO] Surefire report directory: ~/transportation-project/transportation-acq-ejb/target/surefire-reports------------------------------------------------------- T E S T S ------------------------------------------------------- Running com.packt.samples.SampleTest Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.032 sec - in com.packt.samples.SampleTest Results : Tests run: 1, Failures: 0, Errors: 0, Skipped: 0 [INFO] --- maven-jar-plugin:2.4:jar (default-jar) @ transportation-acq-ejb --- [INFO] Building jar: ~/transportation-project/transportation-acq-ejb/target/transportation-acq-ejb-0.0.1-SNAPSHOT.jar [INFO] [INFO] --- maven-install-plugin:2.4:install (default-install) @ transportation-acq-ejb --- [INFO] Installing ~/transportation-project/transportation-acq-ejb-0.0.1-SNAPSHOT.jar to ~/.m2/repository/com/packt/examples/transportation-acq-ejb/0.0.1-SNAPSHOT/transportation-acq-ejb-0.0.1-SNAPSHOT.jar [INFO] Installing ~/transportation-project/transportation-acq-ejb/pom.xml to ~/.m2/repository/com/packt/examples/transportation-acq-ejb/0.0.1-SNAPSHOT/transportation-acq-ejb-0.0.1-SNAPSHOT.pom [INFO] ----------------------------------------------------------- [INFO] BUILD SUCCESS [INFO] -----------------------------------------------------------
So, as we can see, the sequence of operations performed by Maven follows the steps specified in the default lifecycle. You will also notice that each action performed by Maven is delegated to a certain plugin. In order to compile the project, Maven will download and use the specified dependencies (in this case, Java EE API is needed to compile the EJB classes). Plugins and dependencies are downloaded on-demand, and they are saved in the local repository, which is located under the local user home in the /.m2/repository
subdirectory by default.
Once Maven downloads an artifact or a plugin, it will reuse its stored copy and never search the same version of this artifact or plugin in the Maven central repository or in other remote repositories that can be specified in our POM file again. The only exception to this rule regarding the snapshot versions is that if the version of a dependency or plugin is marked with the -SNAPSHOT
suffix, this version is currently on development. For this reason, Maven will periodically attempt to download this artifact from all the remote repositories that have snapshots enabled in their configurations (refer the Configuring repositories section in this chapter).
If we look in the /target
directory, we'll see all the work done by Maven; in this case, the compiled classes, unit test reports, and packaged artifact transportation-acq-ejb-0.0.1-SNAPSHOT.jar
:
Note that if instead of running the previous command, we run the mvn package
command, the lifecycle execution will stop with the package
phase and the artifact will not be installed in the local repository. This can be a problem if the artifact is needed by other projects as a dependency.
The clean lifecycle is responsible for cleaning the build output. Its phases are as follows:
If we run the mvn clean
command, the target directory will be deleted, but not the artifact installed in the local repository:
$ mvn clean
Maven can also be used to generate project documentations in various formats and reports about the project. This is achieved through the site lifecycle. We'll discuss these features in Chapter 4, Managing the Code.