Exercise 1: First Simple Application

Part D: Portable and repeatable project builds with Maven

Objectives

  • Demonstrate the basics of automating the manual steps in part A using the Maven build system.
    Note:
    Using Maven requires only an initial download and installation. Plugins and dependencies will be downloaded from remote repositories as needed. Connectivity to the internet is required until all dependencies have been satisfied.
    Note:
    The people involved with Maven have done a tremendous job at documenting the system and how to get started. If you have not done so, you should become familiar with the fact that the following reference starting points exist. Read through them as you wish. However, know that I go out of my way to make sure you spend as much time as possible on design and JavaEE aspects in class. If you are stuck on Maven -- ask. I know what you are trying to do and can likely point you to an example that is relevant to what you are doing in class. If you are still stuck on Maven issues -- send it to me. I will fix it personally. There is nothing more irritating for you than to be fighting with the builds when you want to be spending more time understanding, designing, trying, and mastering the product of what is being built.
    • Maven Getting Started - This exercise actually mirrors most of the concepts expressed in that paper. I will refer to the Maven site to provide a complete description of each topic. However, this exercise tweeks their example some to put it into context with the preceding and follow-on steps (e.g., how to get Ant and Maven environments to be consistent). Feel free to do their exercise and only scan over this one if you want.
    • Getting Started Guides - this is a collection of short papers on getting started using a particular feature.
    • Plugins - this provides a starting point to locating core plugin documentation.
    • Maven FAQ contains Maven's official FAQ. Contributed FAQ contains a user-maintained FAQ.
    • Books and Articles This has a huge collection of information; which is why you won't find me re-documenting Maven here.
    Note:
    Maven will automatically go out and download any missing dependencies and recursively download what they depend upon. If you are running Maven for the first time, this could result in a significant amount of downloading and may encounter an occasional connection failure with repositories. Once a non-SNAPSHOT version is downloaded (e.g., 1.3), Maven will not re-attempt to download it. Maven will, however, go out and check various resources to stay in sync. If you know you already have everything you need, you can run in off-line mode using the "-o" flag on the command line or its equivalent entry within the settings.xml file. This can save you seconds of build time when disconnected from the Internet.

Steps

  1. Create a pom.xml file in PROJECT_BASEDIR. This will be used to define your entire project. Refer to the Maven POM Reference for details about each element.
    • modelVersion - yes; its required
    • groupId - just as it sounds, this value is used to group related artifacts. groupId is a hierarchical value and the individual names are used to form a directory structure in the Maven repository (e.g., artifacts in the myorg.myproject.foo groupId will be located below the HOME/.m2/repository/myorg/myproject/foo directory).
    • version - Maven has a strong versioning system and versions appended with the word SNAPSHOT are handled differently. Projects with a version ending in -SNAPSHOT are thought to be in constant change, with no official release yet available. Projects with a version lacking the -SNAPSHOT ending are meant to be an official release, with no other variants available with the same tag.
    • dependency.scope - this is used to define the scope the dependency gets applied. scope=compile is the default and is used to describe artifacts that the src/main directory depends upon. These artifacts will be brought along with the module when transitive dependencies are evaluated. If scope is missing, the value is assumed to be scope=compile. scope=test is used to define artifacts which src/test depends upon. These will be made available during testing, but will not be considered a dependency for downstream users of the module. Consult the maven documentation for other scopes, but one other that is commonly used in class is scope=provided. This is similar to scope=compile in that the src/main tree needs it, however like scope=test, it is not carried forward. The downstream module is required to know about the dependency and provide a replacement. This is common for APIs like JavaEE where we may want to provide the API using a downstream provider's artifact rather than the upstream dependency's selection.
      Note:
      Although m2eclipse reads the pom dependency and creates a classpath within Eclipse, it does not honor the differences between the different scope values. All dependencies are blended together. The result is that something may compile and run fine within Eclipse and report a missing class when built at the command line. If that happens, check for classes using artifacts that have been brought in as scope=test.
    • maven-compiler-plugin - this declaration is not necessary for this exercise, but like our Ant script, specify the Java version to make sure we get what we need.
    • properties.project.build.sourceEncoding - this defines the default handling of file content for all plugins within a module. The default is platform-specific if left unspecified. UTF-8 is a reasonable default without going as far as UTF-16.
    <?xml version="1.0"?>
    <project>
        <modelVersion>4.0.0</modelVersion>
    
        <groupId>myorg.myproject</groupId>
        <artifactId>ex1</artifactId>
    
        <name>My First Simple Project</name>
        <version>1.0-SNAPSHOT</version>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>commons-logging</groupId>
                <artifactId>commons-logging</artifactId>
                <version>1.1.1</version>
                <scope>compile</scope>
            </dependency>
    
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.10</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>log4j</groupId>
                <artifactId>log4j</artifactId>
                <version>1.2.13</version>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-compiler-plugin</artifactId>
                    <version>2.5.1</version>
                    <configuration>
                        <source>1.6</source>
                        <target>1.6</target>
                    </configuration>
                </plugin>
            </plugins>
        </build>
    </project>
    > find . -type f
    ./src/main/java/myorg/mypackage/ex1/App.java
    ./src/test/java/myorg/mypackage/ex1/AppTest.java
    ./src/test/resources/log4j.xml
    ./build.properties
    ./build.xml
    ./pom.xml
  2. Note that the pom.xml file is not required to have an assigned schema. However, adding one does allow for XML editing tools to better assist in creating a more detailed POM. Replace the project element from above with the following declarations to assign an XML schema.
    <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">
  3. Run the package target and watch the project compile, assemble, and test.
    $ mvn package
    [INFO] Scanning for projects...
    [INFO]
    [INFO] ------------------------------------------------------------------------
    [INFO] Building My First Simple Project 1.0-SNAPSHOT
    [INFO] ------------------------------------------------------------------------
    [INFO]
    [INFO] --- maven-resources-plugin:2.4.3:resources (default-resources) @ ex1 ---
    [INFO] Using 'UTF-8' encoding to copy filtered resources.
    [INFO] skip non existing resourceDirectory C:\jhu\784\jboss6\solutions\ex1\src\main\resources
    [INFO]
    [INFO] --- maven-compiler-plugin:2.3.2:compile (default-compile) @ ex1 ---
    [INFO] Compiling 1 source file to C:\jhu\784\jboss6\solutions\ex1\target\classes
    [INFO]
    [INFO] --- maven-resources-plugin:2.4.3:testResources (default-testResources) @ ex1 ---
    [INFO] Using 'UTF-8' encoding to copy filtered resources.
    [INFO] Copying 1 resource
    [INFO]
    [INFO] --- maven-compiler-plugin:2.3.2:testCompile (default-testCompile) @ ex1 ---
    [INFO] Compiling 1 source file to C:\jhu\784\jboss6\solutions\ex1\target\test-classes
    [INFO]
    [INFO] --- maven-surefire-plugin:2.5:test (default-test) @ ex1 ---
    [INFO] Surefire report directory: C:\jhu\784\jboss6\solutions\ex1\target\surefire-reports
    
     -------------------------------------------------------
     T E S T S
     -------------------------------------------------------
    Running myorg.mypackage.ex1.AppTest
    INFO  02-02 11:31:53,487 (AppTest.java:testApp:26)  -testApp
    DEBUG 02-02 11:31:53,487 (App.java:returnOne:11)  -Here's One!
    Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.234 sec
    
    Results :
    
    Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
    
    [INFO]
    [INFO] --- maven-jar-plugin:2.3.1:jar (default-jar) @ ex1 ---
    [INFO] Building jar: C:\jhu\784\jboss6\solutions\ex1\target\ex1-1.0-SNAPSHOT.jar
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 3.375s
    [INFO] Finished at: Wed Feb 02 11:31:53 EST 2011
    [INFO] Final Memory: 9M/21M
    [INFO] ------------------------------------------------------------------------
    [WARNING] The requested profile "hsql" could not be activated because it does not exist.
    > find . -type f
    ./src/main/java/myorg/mypackage/ex1/App.java
    ./src/test/java/myorg/mypackage/ex1/AppTest.java
    ./src/test/resources/log4j.xml
    ./build.properties
    ./build.xml
    ./target/classes/myorg/mypackage/ex1/App.class
    ./target/test-classes/log4j.xml
    ./target/test-classes/myorg/mypackage/ex1/AppTest.class
    ./target/log4j-out.txt
    ./target/surefire-reports/myorg.mypackage.ex1.AppTest.txt
    ./target/surefire-reports/TEST-myorg.mypackage.ex1.AppTest.xml
    ./target/exported-pom.xml
    ./target/ex1-1.0-SNAPSHOT.jar
    ./pom.xml
    Note:
    src/main/java classes were built in the target/classes directory, src/test/java classes where built in the target/test-classes directory, and src/test/resources where copied to the target/test-classes directory by the maven-compiler-plugin with no configuration help. All Maven defaults were take (except for specifying JavaSE 6 and specifying UTF-8 for files processed).
    Note:
    Test cases were run and their reports were placed in target/surefire-reports. Surefire is a Maven plugin that supports multiple test frameworks, but defaults to JUnit. We didn't have to configure it because we structured our project using Maven directory structure and used the default packaging=jar module type (since packaging=jar is the default, it could be left unspecified). Many of the standard features are enacted when for modules with packaging=jar type.
    Note:
    The build.xml and build.properties file from our work with Ant is still allowed to exist. We could even delegate from Maven to Ant using the maven-antrun-plugin if we had legacy build.xml scripts that we wanted to leverage.
    Note:
    The [WARNING] Using platform encoding (Cp1252 actually) to copy filtered resources, i.e. build is platform dependent! is avoided by using the following to the top of the pom.xml
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        </properties>
  4. For *fun*, lets add a README that could be used to describe something about your project and have it be processed as part of the documentation for the module. You do not need to do this for class projects, but walking through this may be helpful in understanding how the class website is created from the source you have on your disk. Maven supports a couple of documentation generation languages, but lets just use HTML to keep this simple. Place the following content to src/site/resources/README.html
    <?xml version="1.0"?>
    <html>
        <head>
            <title>My First Project</title>
        </head>
    <body>
        <section><h1>My First Project</h1></section>
    
        <p/>
        This is my first project. Take a look at 
    
        <p/>
        <ul>
            <li>this ....</li>
            <li>that ....</li>
            <li>or <a href="./index.html">go home</a></li>
        </ul>
    
        </section>
    </body>
    </html>
  5. The above is enough to provide the page. Now add a link to it from the project menu. Add the following content to src/site/site.xml
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <project name="${project.name}">
      <body>
        <menu name="Content">
            <item name="README" href="README.html"/>
        </menu>
      </body>
    </project>
    > find . -type f
    ./src/main/java/myorg/mypackage/ex1/App.java
    ./src/test/java/myorg/mypackage/ex1/AppTest.java
    ./src/test/resources/log4j.xml
    ./src/site/resources/README.html
    ./src/site/site.xml
    ./build.properties
    ./build.xml
    ./pom.xml
  6. Build the site and open target/site/index.html in your browser. You should see a link to the README on the left side.
    > mvn site
    [INFO] Scanning for projects...
    [INFO]
    ...
    > find ./target -type f
    ./target/site/integration.html
    ./target/site/dependencies.html
    ./target/site/issue-tracking.html
    ./target/site/license.html
    ./target/site/mail-lists.html
    ./target/site/index.html
    ./target/site/project-summary.html
    ./target/site/source-repository.html
    ./target/site/team-list.html
    ./target/site/project-info.html
    ./target/site/css/maven-theme.css
    ./target/site/css/maven-base.css
    ./target/site/css/print.css
    ./target/site/images/external.png
    ./target/site/README.html
    Warning:
    Maven site reporting has been redesigned for Maven 3 and the above does not generate the desired content as described without specifying a new site plugin version (which requires Maven 3). Add the following to the build area of your pom.xml to restore full site generation.
        <build>
            ...
            <pluginManagement>
              <plugins>
                <plugin>
                    <groupId>org.apache.maven.plugins</groupId>
                    <artifactId>maven-site-plugin</artifactId>
                    <version>3.1</version>
                </plugin>
                <plugin> 
                    <artifactId>maven-project-info-reports-plugin</artifactId>
                    <groupId>org.apache.maven.plugins</groupId>
                    <version>2.5</version>
                </plugin>
              </plugins>
            </pluginManagement>
            ...
        </build>
  7. Okay, that was a lot of work to just copy an html file. Now lets add javadoc to our project and create a link to it. Add the following contents to the bottom of the pom.xml file.
        <reporting>
            <plugins>
                <plugin> 
                    <artifactId>maven-javadoc-plugin</artifactId>
                    <groupId>org.apache.maven.plugins</groupId>
                    <version>2.8.1</version>
                    <configuration>
                        <detectLinks/>
                        <show>private</show>
                        <source>1.6</source>
                        <links>
                            <link>http://download.oracle.com/javaee/6/api/</link>
                            <link>http://download.oracle.com/javase/6/docs/api/</link>
                        </links>
                    </configuration>
                </plugin>
            </plugins>
        </reporting>
  8. We could create a link the the apidocs/index.html like we did with README.html, but that would be something we'd keep having to update each time we added a new report. Lets add a property to the site.xml menu so a link to Javadoc and other reports can drop in automatically.
    <?xml version="1.0" encoding="ISO-8859-1"?>
    <project name="${project.name}">
      <body>
        <menu name="Content">
            <item name="README" href="README.html"/>
        </menu>
    
        <menu ref="reports"/>
    
      </body>
    </project>
  9. Re-generate the site documentation with the site target. Open the target/site/index.html page and you should now see a menu item for "Project Reports" -> "JavaDocs". Our App class should be included in the Javadoc.
    Note:
    The pom.xml file is the main configuration source for 99% of what you develop with Maven. There is an additional $HOME/.m2/settings.xml file where you can specify build site-specific properties. These will be available to all pom.xml files. You want to be careful not to over-populate the settings.xml file (taking advantage of its re-usable specification) since it will make you pom.xml files too dependent on a particulate build site. Refer to the Settings Descriptor for detailed information on settings.xml.
    Note:
    The following provides a step-wise generation of the settings.xml file you put in place during ex0. Read thru this for reference since you likely already have everything in place you need.
  10. Let's start a settings.xml file to store properties that are specific to out build site. You can find details about each setting at the following URL.
    <?xml version="1.0"?>
    <settings 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/settings-1.0.0.xsd">
    
    </settings>
    Note:
    The following discussion on settings.xml covers much of the work you have already done in exercise 0. It is included here just to provide additional discussion of the topic.
  11. The first thing Windows XP users will want to do is provide an override for the localRepository. Provide a custom path that does not contain spaces. This value will default to a "$HOME/.m2/repository" directory.
        <!-- this overrides the default $HOME/.m2/repository location. -->
        <localRepository>c:/jhu/repository</localRepository>
  12. Add the following specification to either the settings.xml file or the local pom.xml file. If you specify it to the local pom.xml file -- it will only apply to that project. If you specify it in the settings.xml file -- it will be global to all projects in your area. More will be covered on this later. However, it should be noted that this profile is not active unless someone specifically asks for it (-Pdebugger) or the "debugger" environment variable is set (-Ddebugger=(anything)).
            <profile>
                <id>debugger</id>
                <!-- this should only be activated when performing interactive
                     debugging -->
                <activation>
                    <property>
                        <name>debugger</name>
                    </property>
                </activation>
                <properties>
                    <surefire.argLine>-Xrunjdwp:transport=dt_socket,server=y,suspend=y,address=8000 -Xnoagent -Djava.compiler=NONE</surefire.argLine>
                </properties>                                  
            </profile>        
    Note:
    Although not needed for this class -- at times you will need access to a dependency that is not available in a Maven repository. COTS libraries are generally not available at ibiblio.org. You must download it and manually install it locally.
  13. This step will go though importing a stand-alone archive into the repository to resolve any dependencies. Start by declaring a dependency before we do the import. Note that a new scope property was added. See the Dependency Mechanism Intro Page for a discussion of scope, but in this case it is indicating that it should only be present on the command line and not the runtime classpath.
            <dependency>
                <groupId>foo</groupId>
                <artifactId>bar</artifactId>
                <version>1.1</version>
                <scope>provided</scope>
            </dependency>
    > mvn package
    [INFO] Scanning for projects...
    [INFO]
    [INFO] ------------------------------------------------------------------------
    [INFO] Building My First Simple Project 1.0-SNAPSHOT
    [INFO] ------------------------------------------------------------------------
    Downloading: http://webdev.apl.jhu.edu/~jcs/maven2/foo/bar/1.1/bar-1.1.pom
    Downloading: http://webdev.apl.jhu.edu/~jcs/maven2-snapshot/foo/bar/1.1/bar-1.1.pom
    Downloading: http://repo1.maven.org/maven2/foo/bar/1.1/bar-1.1.pom
    [WARNING] The POM for foo:bar:jar:1.1 is missing, no dependency information available
    Downloading: http://webdev.apl.jhu.edu/~jcs/maven2/foo/bar/1.1/bar-1.1.jar
    Downloading: http://webdev.apl.jhu.edu/~jcs/maven2-snapshot/foo/bar/1.1/bar-1.1.jar
    Downloading: http://repo1.maven.org/maven2/foo/bar/1.1/bar-1.1.jar
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD FAILURE
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 1.437s
    [INFO] Finished at: Wed Feb 02 12:20:51 EST 2011
    [INFO] Final Memory: 2M/15M
    [INFO] ------------------------------------------------------------------------
    [ERROR] Failed to execute goal on project ex1: Could not resolve dependencies for project myorg.myproject:ex1:jar:1.0-SNAPSHOT: Could not fi
    nd artifact foo:bar:jar:1.1 in webdev-baseline (http://webdev.apl.jhu.edu/~jcs/maven2) -> [Help 1]
    [ERROR]
    [ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
    [ERROR] Re-run Maven using the -X switch to enable full debug logging.
    [ERROR]
    [ERROR] For more information about the errors and possible solutions, please read the following articles:
    [ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/DependencyResolutionException
  14. The old error message provided for Maven 2 was much better if a manual install is what you really needed. The newer (Maven 3) one does not provide instruction. In this case, manually install a jar file that represents the declaration. Assign it a groupId of foo, an artifactId of bar, and a version of 1.1. Don't forget to add the -DgeneratePom=true or you will get a download warning everytime you try to build. All we need is a valid .jar file. If you don't have one laying around, just create one with valid structure.
    $ mvn install:install-file -DgroupId=foo -DartifactId=bar \
    > -Dversion=1.1 -Dpackaging=jar -Dfile=bar.jar \
    > -DgeneratePom=true
    [INFO] Scanning for projects...
    [INFO]
    [INFO] ------------------------------------------------------------------------
    [INFO] Building My First Simple Project 1.0-SNAPSHOT
    [INFO] ------------------------------------------------------------------------
    [INFO]
    [INFO] --- maven-install-plugin:2.3.1:install-file (default-cli) @ ex1 ---
    [INFO] Installing C:\jhu\784\jboss6\solutions\ex1\bar.jar to c:\jhu\repository\foo\bar\1.1\bar-1.1.jar
    [INFO] Installing C:\Documents and Settings\jcstaff\mvninstall2771571397162981253.pom to c:\jhu\repository\foo\bar\1.1\bar-1.1.pom
    [INFO] ------------------------------------------------------------------------
    [INFO] BUILD SUCCESS
    [INFO] ------------------------------------------------------------------------
    [INFO] Total time: 1.032s
    [INFO] Finished at: Wed Feb 02 12:25:12 EST 2011
    [INFO] Final Memory: 2M/15M
    [INFO] ------------------------------------------------------------------------
    $ find c:/jhu/repository/foo/ -type f
    c:/jhu/repository/foo/bar/1.1/bar-1.1.jar
    c:/jhu/repository/foo/bar/1.1/bar-1.1.jar.lastUpdated
    c:/jhu/repository/foo/bar/1.1/bar-1.1.pom
    c:/jhu/repository/foo/bar/1.1/bar-1.1.pom.lastUpdated
    c:/jhu/repository/foo/bar/1.1/_maven.repositories
    c:/jhu/repository/foo/bar/maven-metadata-local.xml
    
    
    $ more c:/jhu/repository/foo/bar/1.1/bar-1.1.pom
    <?xml version="1.0" encoding="UTF-8"?>
    <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/P
    OM/4.0.0"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
      <modelVersion>4.0.0</modelVersion>
      <groupId>foo</groupId>
      <artifactId>bar</artifactId>
      <version>1.1</version>
      <description>POM was created from install:install-file</description>
    </project>
  15. Now try running "mvn package" and it should successfully resolve the fake dependency on the bar.jar.

Useful Commands

  • Getting the "Effective POM"

    This is useful to determine what all the delegation summed up to.

    $ mvn help:effective-pom 
    
    ...
    <!-- ====================================================================== -->
    <!--                                                                        -->
    <!-- Effective POM for project 'myorg.myproject:ex1:jar:1.0-SNAPSHOT'       -->
    <!--                                                                        -->
    <!-- ====================================================================== -->
    
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://w
    ache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
      <modelVersion>4.0.0</modelVersion>
      <groupId>myorg.myproject</groupId>
      <artifactId>ex1</artifactId>
      <version>1.0-SNAPSHOT</version>
      <name>My First Simple Project</name>
      <properties>
        <jboss.home>c:/apps/jboss-6.1.0.Final</jboss.home>
        <jboss.host>localhost</jboss.host>
        <jboss.password>password</jboss.password>
        <jboss.protocol>http</jboss.protocol>
        <jboss.server>ejava-jboss6</jboss.server>
        <jboss.servlet.port>8080</jboss.servlet.port>
        <jboss.user>admin</jboss.user>
        <m2.repo>c:/jhu/repository</m2.repo>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
      </properties>
  • Getting the "Effective Settings"

    There are various ways to implement local properties that do the work of the global settings.xml. To get the net result, use the following

    mvn help:effective-settings
    
    ...
    
    <settings xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.a
    pache.org/SETTINGS/1.1.0 http://maven.apache.org/xsd/settings-1.1.0.xsd">
      <localRepository xmlns="http://maven.apache.org/SETTINGS/1.1.0">c:\jhu\repository</localRepository>
      <activeProfiles xmlns="http://maven.apache.org/SETTINGS/1.1.0">
        <activeProfile>ejavaPC</activeProfile>
        <activeProfile>jboss6</activeProfile>
        <activeProfile>hsql</activeProfile>
        <activeProfile>webdev-repositories</activeProfile>
      </activeProfiles>
      <pluginGroups xmlns="http://maven.apache.org/SETTINGS/1.1.0">
        <pluginGroup>org.apache.maven.plugins</pluginGroup>
        <pluginGroup>org.codehaus.mojo</pluginGroup>
      </pluginGroups>
    </settings>
    ...
  • Getting help for a plugin
    > mvn help:describe -Dplugin=surefire -Dfull=true 
    
    ...
    
    Mojos:
    
    ===============================================
    Goal: 'test'
    ===============================================
    Description:
    
    Run tests using Surefire.
    
    Implementation: org.apache.maven.plugin.surefire.SurefirePlugin
    Language: java
    Bound to Phase: test
    
    Parameters:
     -----------------------------------------------
    
    [0] Name: argLine
    Type: java.lang.String
    Required: false
    Directly editable: true
    Description:
    
    Arbitrary options to set on the command line.
    
    ...

Summary

During this exercise, you were able to establish a project which was understood by Maven. Once Maven-compliant, each plugin can be added to perform different tasks for development. By the time we start adding databases, building EARs, and deploying to application servers, we can use all the plugin help we can get.