Enterprise Java Development@TOPIC@

Chapter 10. Maven Basics

10.1. Directory Structure
10.1.1. Source Tree
10.1.2. Build Tree
10.2. Maven POM
10.2.1. Packaging
10.2.2. Project Identity
10.2.3. Maven Repositories
10.2.4. Properties
10.2.5. Dependencies
10.2.6. Build Definition
10.3. Maven Commands
|-- pom.xml
|-- src
|   |-- main
|   `-- test
`-- target
    |-- classes
    |-- ex1-1.0-SNAPSHOT.jar
    |-- surefire-reports
    `-- test-classes
target
|-- classes
|   `-- myorg
|       `-- mypackage
|           `-- ex1
|               `-- App.class
|-- ex1-1.0-SNAPSHOT.jar
|-- log4j-out.txt
|-- surefire-reports
|   |-- myorg.mypackage.ex1.AppTest.txt
|   `-- TEST-myorg.mypackage.ex1.AppTest.xml
`-- test-classes
    |-- log4j.xml
    `-- myorg
        `-- mypackage
            `-- ex1
                `-- AppTest.class
classes

An exploded directory tree for built artifacts to be placed into the module archive

test-classes

An exploded directory tree for built artifacts used for test

*-reports

Results of unit and integration testing

{artifactId}-{version}.jar

Results of unit and integration testing

log4j-out.txt

An example output file of the build/tests written to the target directory


<?xml version="1.0"?>
<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>

    <groupId>myorg.myproject</groupId>
    <artifactId>ex1</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>My First Simple Project</name>
        ...
    <properties>
        ...
    </properties>

    <dependencies>
        ...
    <dependencies>

    <build>
        <plugins>
            ...
        </plugins>
    </build>
</project>

  1. Maven will first look for a dependency artifact in the local repository

  2. Maven will then look for a dependency artifact in a remote repository like ibiblio

  3. Maven will search all known repositories until the artifact is found or all repositories have been checked

  4. Maven will install module artifacts into the local repository during the install phase of the build

    $ mvn install
        ...
    [INFO] --- maven-install-plugin:2.3.1:install (default-install) @ ex1 ---
    [INFO] Installing /home/jcstaff/proj/ejava-javaee/solutions/ex1/target/ex1-1.0-SNAPSHOT.jar to 
        /home/jcstaff/.m2/repository/myorg/myproject/ex1/1.0-SNAPSHOT/ex1-1.0-SNAPSHOT.jar
    [INFO] Installing /home/jcstaff/proj/ejava-javaee/solutions/ex1/pom.xml to 
        /home/jcstaff/.m2/repository/myorg/myproject/ex1/1.0-SNAPSHOT/ex1-1.0-SNAPSHOT.pom
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
                    

Use -U to force an update check

Maven will limit its search of a remote repository to expressed time limits. If it attempts and fails to locate an artifact from a remote repository it will not re-attempt to query that repository until the time limit expires. Sometimes the failure has nothing to do with the repository not having the artifact (e.g., wireless network down) and when you clear the error you can force Maven to retry before the timeout period expires by adding a -U to the command line.

Use the -o offline flag to eliminate repository checks

Many times Maven will be too aggressive searching for artifacts you already know are not of value to the current build. You can tell Maven to work in an offline mode to bypass the work involved. This is helpful when you are disconnected from the network but will fail if you are truly missing a required artifact. You can activate/deactivate the offline more consistently using an element in the settings.xml


<offline>false</offline>

Use dependency:go-offline prior to network/repo outage

Maven will lazily download required artifacts on-demand as different plugins are executed. If you know you will be separated from the network or a key repository will have an upcoming outage -- you can prepare your local environment by having Maven eagerly resolve and download all dependencies using the dependency:go-offline goal.


$ mvn dependency:go-offline
[INFO] Scanning for projects...

<dependencies>
        <dependency>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-api</artifactId>
            <version>1.7.25</version>
            <scope>compile</scope>
        </dependency>

        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
...
</dependencies>
GAV

Must provide its groupId, artifactId, and version for each dependency

scope

Defines when the dependency applies (default=compile)

type

Defines the artifact type of ther module (default=jar)

Value directly relates to the project packaging element of the dependency

|-- ejbsessionBankImpl
|       |-- ejbsessionBankImpl-3.0.2013.2-SNAPSHOT.jar
|-- ejbsessionBankEJB
|       |-- ejbsessionBankEJB-3.0.2013.2-SNAPSHOT.jar
|-- ejbsessionBankWAR
|       |-- ejbsessionBankWAR-3.0.2013.2-SNAPSHOT.war
|-- ejbsessionBankEAR
|       |-- ejbsessionBankEAR-3.0.2013.2-SNAPSHOT.ear
classifier

Defines a special type of artifact/custom from a module

`-- target
...
    |-- txHotelDAO-3.0.2013.2-SNAPSHOT.jar
    |-- txHotelDAO-3.0.2013.2-SNAPSHOT-sources.jar
    `-- txHotelDAO-3.0.2013.2-SNAPSHOT-tests.jar

<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-compiler-plugin</artifactId>
            <version>3.7.0</version>
            <configuration>
                <source>${java.source.version}</source>
                <target>${java.target.version}</target>
            </configuration>
        </plugin>
         <!-- surefire.argLine is set in debugger profile -->
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-surefire-plugin</artifactId>
            <version>2.22</version>
            <configuration>
                <argLine>${surefire.argLine}</argLine>
            </configuration>
        </plugin>
        ...
  • New plugins can be added, but will need to be wired into a specific lifecycle phase of the build.

    
    <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-failsafe-plugin</artifactId>
        <version>${maven-failsafe-plugin.version}</version>
        <configuration>
            <argLine>${surefire.argLine}</argLine>
        </configuration>
        <executions>
            <execution> <!-- run the tests here -->
               <id>integration-tests</id>
                   <phase>integration-test</phase>
               <goals>
                   <goal>integration-test</goal>
               </goals>
            </execution>
            <execution> <!--  delay failures to after undeploy -->
                <id>verify</id>
                <phase>verify</phase>
                <goals>
                    <goal>verify</goal>
                </goals>
            </execution>
        </executions>
    </plugin>

    The above example shows the failsafe plugin being configured to share some properties with surefire and have specific goals wired into the integration-test and verify lifecycle phases.

$ mvn (phase) (plugin:goal) -D(system-property) -P(profile)
        
  • phase

    clean

    Remove contents of target tree

    test

    Build the src/main and src/test tree and execute the unit tests as defined by the surefire plugin

    pre-integration

    Perform unit tests and perform any steps required to ready for integration test

    integration-test

    Perform integration tests as defined by the failsafe plugin

    post-integration-test

    Tear down anything required to perform integration tests

    verify

    Evaluate results of integration tests

    install

    Install module artifacts into local repository

  • (plugin:goal)

    • Manually trigger a plugin goal without a specific build lifecycle

    • ex. jetty:run, dependency:tree, or dependency:help

  • -D(system-property)

    • Manually define a system property key or key and value to be used as a property in the build

    • Must configure surefire/failsafe to promote these as properties Junit -- these are system properties of the maven build and not of the JVM tasks kicked off by the maven build.

  • -P(profile)

    • Manually trigger build configurations latched by a profile

    • e.g., which DB driver to use

  • -P!(profile)

    • Manually turn off a profile

    • e.g., turn off a profile activated by a rule or settings.xml

    Use -P\!(profile) with bash shell

    The bash shell requires the bang ("!") character to be escaped. Use -P\!(profile) when using the bash shell.