Apache Maven Getting Started Guide
Apache Maven Getting Started Guide
Apache Maven Getting Started Guide
This guide is intended as a reference for those working with Maven for the first time, but is also intended to
serve as a cookbook with self-contained references and solutions for common use cases. For first time users, it
is recommended that you step through the material in a sequential fashion. For users more familiar with Maven,
this guide endeavours to provide a quick solution for the need at hand. It is assumed at this point that you have
downloaded Maven and installed Maven on your local machine. If you have not done so please refer to the
Download and Installation (../../download.html) instructions.
Ok, so you now have Maven installed and we're ready to go. Before we jump into our examples we'll very briefly
go over what Maven is and how it can help you with your daily work and collaborative efforts with team
members. Maven will, of course, work for small projects, but Maven shines in helping teams operate more
effectively by allowing team members to focus on what the stakeholders of a project require. You can leave the
build infrastructure to Maven!
Sections
▪ What is Maven? (./index.html#what-is-maven)
▪ How can Maven benefit my development process? (./index.html#how-can-maven-benefit-my-development-
process)
▪ How do I setup Maven? (./index.html#how-do-i-setup-maven)
▪ How do I make my first Maven project? (./index.html#how-do-i-make-my-first-maven-project)
▪ How do I compile my application sources? (./index.html#how-do-i-compile-my-application-sources)
▪ How do I compile my test sources and run my unit tests? (./index.html#how-do-i-compile-my-test-sources-
and-run-my-unit-tests)
▪ How do I create a JAR and install it in my local repository? (./index.html#how-do-i-create-a-jar-and-install-it-
in-my-local-repository)
▪ What is a SNAPSHOT version? (./index.html#what-is-a-snapshot-version)
▪ How do I use plugins? (./index.html#how-do-i-use-plugins)
▪ How do I add resources to my JAR? (./index.html#how-do-i-add-resources-to-my-jar)
▪ How do I filter resource files? (./index.html#how-do-i-filter-resource-files)
▪ How do I use external dependencies? (./index.html#how-do-i-use-external-dependencies)
▪ How do I deploy my jar in my remote repository? (./index.html#how-do-i-deploy-my-jar-in-my-remote-
repository)
▪ How do I create documentation? (./index.html#how-do-i-create-documentation)
▪ How do I build other types of projects? (./index.html#how-do-i-build-other-types-of-projects)
▪ How do I build more than one project at once? (./index.html#how-do-i-build-more-than-one-project-at-once)
What is Maven?
At first glance Maven can appear to be many things, but in a nutshell Maven is an attempt to apply patterns to a
project's build infrastructure in order to promote comprehension and productivity by providing a clear path in the
use of best practices. Maven is essentially a project management and comprehension tool and as such provides
a way to help with managing:
▪ Builds
▪ Documentation
▪ Reporting
▪ Dependencies
▪ SCMs
▪ Releases
▪ Distribution
If you want more background information on Maven you can check out The Philosophy of Maven (../../
background/philosophy-of-maven.html) and The History of Maven (../../background/history-of-maven.html).
Now let's move on to how you, the user, can benefit from using Maven.
Now that we have covered a little bit of the history and purpose of Maven let's get into some real examples to
get you up and running with Maven!
On to creating your first project! In order to create the simplest of Maven projects, execute the following from the
command line:
Once you have executed this command, you will notice a few things have happened. First, you will notice that a
directory named my-app has been created for the new project, and this directory contains a file named
pom.xml that should look like this:
1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/200
1/XMLSchema-instance"
2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/
maven-4.0.0.xsd">
>
3. <modelVersion>4.0.0<
</modelVersion>
4.
5. <groupId>com.mycompany.app<
</groupId>
6. <artifactId>my-app<
</artifactId>
7. <version>1.0-SNAPSHOT<
</version>
8.
9. <name>my-app<
</name>
10. <!-- FIXME change it to the project's website -->
11. <url>http://www.example.com<
</url>
12.
13. <properties>
14. <project.build.sourceEncoding>UTF-8<
</project.build.sourceEncoding>
15. <maven.compiler.source>1.7<
</maven.compiler.source>
16. <maven.compiler.target>1.7<
</maven.compiler.target>
17. </properties>
18.
19. <dependencies>
20. <dependency>
21. <groupId>junit<
</groupId>
22. <artifactId>junit<
</artifactId>
23. <version>4.11<
</version>
24. <scope>test<
</scope>
25. </dependency>
26. </dependencies>
27.
28. <build>
29. <pluginManagement><!-- lock down plugins versions to avoid using Maven defaults
(may be moved to parent pom) -->
30. ... lots of helpful plugins
31. </pluginManagement>
32. </build>
33. </project>
pom.xml contains the Project Object Model (POM) for this project. The POM is the basic unit of work in Maven.
This is important to remember because Maven is inherently project-centric in that everything revolves around
the notion of a project. In short, the POM contains every important piece of information about your project and
is essentially one-stop-shopping for finding anything related to your project. Understanding the POM is
important and new users are encouraged to refer to the Introduction to the POM (../introduction/introduction-to-
the-pom.html).
This is a very simple POM but still displays the key elements every POM contains, so let's walk through each of
them to familiarize you with the POM essentials:
For a complete reference of what elements are available for use in the POM please refer to our POM Reference
(/ref/current/maven-model/maven.html). Now let's get back to the project at hand.
After the archetype generation of your first project you will also notice that the following directory structure has
been created:
my-app
|-- pom.xml
`-- src
|-- main
| `-- java
| `-- com
| `-- mycompany
| `-- app
| `-- App.java
`-- test
`-- java
`-- com
`-- mycompany
`-- app
`-- AppTest.java
As you can see, the project created from the archetype has a POM, a source tree for your application's sources
and a source tree for your test sources. This is the standard layout for Maven projects (the application sources
reside in ${project.basedir}/src/main/java and test sources reside in
${project.basedir}/src/test/java , where ${project.basedir} represents the directory containing
pom.xml ).
If you were to create a Maven project by hand this is the directory structure that we recommend using. This is a
Maven convention and to learn more about it you can read our Introduction to the Standard Directory Layout (../
introduction/introduction-to-the-standard-directory-layout.html).
Now that we have a POM, some application sources, and some test sources you are probably asking...
Upon executing this command you should see output like the following:
The first time you execute this (or any other) command, Maven will need to download all the plugins and related
dependencies it needs to fulfill the command. From a clean installation of Maven, this can take quite a while (in
the output above, it took almost 4 minutes). If you execute the command again, Maven will now have what it
needs, so it won't need to download anything new and will be able to execute the command much more quickly.
As you can see from the output, the compiled classes were placed in ${project.basedir}/target/classes ,
which is another standard convention employed by Maven. So, if you're a keen observer, you'll notice that by
using the standard conventions, the POM above is very small and you haven't had to tell Maven explicitly where
any of your sources are or where the output should go. By following the standard Maven conventions, you can
get a lot done with very little effort! Just as a casual comparison, let's take a look at what you might have had to
do in Ant (http://ant.apache.org) to accomplish the same thing (../../ant/build-a1.xml).
Now, this is simply to compile a single tree of application sources and the Ant script shown is pretty much the
same size as the POM shown above. But we'll see how much more we can do with just that simple POM!
mvn test
Upon executing this command you should see output like the following:
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< com.mycompany.app:my-app >----------------------
[INFO] Building my-app 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ my-app ---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory <dir>/my-app/src/main/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ my-app ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:testResources (default-testResources) @ my-app
---
[INFO] Using 'UTF-8' encoding to copy filtered resources.
[INFO] skip non existing resourceDirectory <dir>/my-app/src/test/resources
[INFO]
[INFO] --- maven-compiler-plugin:3.8.0:testCompile (default-testCompile) @ my-app ---
[INFO] Changes detected - recompiling the module!
[INFO] Compiling 1 source file to <dir>/my-app/target/test-classes
[INFO]
[INFO] --- maven-surefire-plugin:2.22.1:test (default-test) @ my-app ---
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.mycompany.app.AppTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.025 s - in co
m.mycompany.app.AppTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.881 s
[INFO] Finished at: 2020-07-12T12:00:33+01:00
[INFO] ------------------------------------------------------------------------
▪ Maven downloads more dependencies this time. These are the dependencies and plugins necessary for
executing the tests (it already has the dependencies it needs for compiling and won't download them again).
▪ Before compiling and executing the tests Maven compiles the main code (all these classes are up to date
because we haven't changed anything since we compiled last).
If you simply want to compile your test sources (but not execute the tests), you can execute the following:
mvn test-compile
Now that you can compile your application sources, compile your tests, and execute the tests, you'll want to
move on to the next logical step so you'll be asking ...
mvn package
You can now take a look in the ${project.basedir}/target directory and you will see the generated JAR file.
Now you'll want to install the artifact you've generated (the JAR file) in your local repository
( ${user.home}/.m2/repository is the default location). For more information on repositories you can refer to
our Introduction to Repositories (../introduction/introduction-to-repositories.html) but let's move on to installing
our artifact! To do so execute the following command:
mvn install
Upon executing this command you should see the following output:
[INFO] Scanning for projects...
[INFO]
[INFO] ----------------------< com.mycompany.app:my-app >----------------------
[INFO] Building my-app 1.0-SNAPSHOT
[INFO] --------------------------------[ jar ]---------------------------------
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:resources (default-resources) @ my-app ---
...
[INFO] --- maven-compiler-plugin:3.8.0:compile (default-compile) @ my-app ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-resources-plugin:3.0.2:testResources (default-testResources) @ my-app
---
...
[INFO] --- maven-compiler-plugin:3.8.0:testCompile (default-testCompile) @ my-app ---
[INFO] Nothing to compile - all classes are up to date
[INFO]
[INFO] --- maven-surefire-plugin:2.22.1:test (default-test) @ my-app ---
[INFO]
[INFO] -------------------------------------------------------
[INFO] T E S T S
[INFO] -------------------------------------------------------
[INFO] Running com.mycompany.app.AppTest
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0, Time elapsed: 0.025 s - in co
m.mycompany.app.AppTest
[INFO]
[INFO] Results:
[INFO]
[INFO] Tests run: 1, Failures: 0, Errors: 0, Skipped: 0
[INFO]
[INFO]
[INFO] --- maven-jar-plugin:3.0.2:jar (default-jar) @ my-app ---
[INFO] Building jar: <dir>/my-app/target/my-app-1.0-SNAPSHOT.jar
[INFO]
[INFO] --- maven-install-plugin:2.5.2:install (default-install) @ my-app ---
[INFO] Installing <dir>/my-app/target/my-app-1.0-SNAPSHOT.jar to <local-repository>/co
m/mycompany/app/my-app/1.0-SNAPSHOT/my-app-1.0-SNAPSHOT.jar
[INFO] Installing <dir>/my-app/pom.xml to <local-repository>/com/mycompany/app/my-ap
p/1.0-SNAPSHOT/my-app-1.0-SNAPSHOT.pom
[INFO] ------------------------------------------------------------------------
[INFO] BUILD SUCCESS
[INFO] ------------------------------------------------------------------------
[INFO] Total time: 1.678 s
[INFO] Finished at: 2020-07-12T12:04:45+01:00
[INFO] ------------------------------------------------------------------------
Note that the surefire plugin (which executes the test) looks for tests contained in files with a particular naming
convention. By default the tests included are:
▪ **/*Test.java
▪ **/Test*.java
▪ **/*TestCase.java
You have walked through the process for setting up, building, testing, packaging, and installing a typical Maven
project. This is likely the vast majority of what projects will be doing with Maven and if you've noticed,
everything you've been able to do up to this point has been driven by an 18-line file, namely the project's model
or POM. If you look at a typical Ant build file (../../ant/build-a1.xml) that provides the same functionality that
we've achieved thus far you'll notice it's already twice the size of the POM and we're just getting started! There
is far more functionality available to you from Maven without requiring any additions to our POM as it currently
stands. To get any more functionality out of our example Ant build file you must keep making error-prone
additions.
So what else can you get for free? There are a great number of Maven plugins that work out of the box with
even a simple POM like we have above. We'll mention one here specifically as it is one of the highly prized
features of Maven: without any work on your part this POM has enough information to generate a web site for
your project! You will most likely want to customize your Maven site but if you're pressed for time all you need to
do to provide basic information about your project is execute the following command:
mvn site
There are plenty of other standalone goals that can be executed as well, for example:
mvn clean
This will remove the target directory with all the build data before starting so that it is fresh.
1. <project xmlns="http://maven.apache.org/POM/4.0.0"
2. ...
3. <groupId>...<
</groupId>
4. <artifactId>my-app<
</artifactId>
5. ...
6. <version>1.0-SNAPSHOT<
</version>
7. <name>Maven Quick Start Archetype<
</name>
8. ...
The SNAPSHOT value refers to the 'latest' code along a development branch, and provides no guarantee the
code is stable or unchanging. Conversely, the code in a 'release' version (any version value without the suffix
SNAPSHOT ) is unchanging.
In other words, a SNAPSHOT version is the 'development' version before the final 'release' version. The
SNAPSHOT is "older" than its release.
For this example, we will configure the Java compiler to allow JDK 5.0 sources. This is as simple as adding this
to your POM:
1. ...
2. <build>
3. <plugins>
4. <plugin>
5. <groupId>org.apache.maven.plugins</groupId>
6. <artifactId>maven-compiler-plugin</artifactId>
7. <version>3.3</version>
8. <configuration>
9. <source>1.5</source>
10. <target>1.5</target>
11. </configuration>
12. </plugin>
13. </plugins>
14. </build>
15. ...
You'll notice that all plugins in Maven look much like a dependency - and in some ways they are. This plugin will
be automatically downloaded and used - including a specific version if you request it (the default is to use the
latest available).
The configuration element applies the given parameters to every goal from the compiler plugin. In the above
case, the compiler plugin is already used as part of the build process and this just changes the configuration. It
is also possible to add new goals to the process, and configure specific goals. For information on this, see the
Introduction to the Build Lifecycle (../introduction/introduction-to-the-lifecycle.html).
To find out what configuration is available for a plugin, you can see the Plugins List (../../plugins/) and navigate to
the plugin and goal you are using. For general information about how to configure the available parameters of a
plugin, have a look at the Guide to Configuring Plugins (../mini/guide-configuring-plugins.html).
You see below in our example we have added the directory ${project.basedir}/src/main/resources into
which we place any resources we wish to package in our JAR. The simple rule employed by Maven is this: any
directories or files placed within the ${project.basedir}/src/main/resources directory are packaged in your
JAR with the exact same structure starting at the base of the JAR.
my-app
|-- pom.xml
`-- src
|-- main
| |-- java
| | `-- com
| | `-- mycompany
| | `-- app
| | `-- App.java
| `-- resources
| `-- META-INF
| `-- application.properties
`-- test
`-- java
`-- com
`-- mycompany
`-- app
`-- AppTest.java
So you can see in our example that we have a META-INF directory with an application.properties file within
that directory. If you unpacked the JAR that Maven created for you and took a look at it you would see the
following:
|-- META-INF
| |-- MANIFEST.MF
| `-- application.properties
| `-- maven
| `-- com.mycompany.app
| `-- my-app
| |-- pom.properties
| `-- pom.xml
`-- com
`-- mycompany
`-- app
`-- App.class
As you can see, the contents of ${project.basedir}/src/main/resources can be found starting at the base
of the JAR and our application.properties file is there in the META-INF directory. You will also notice some
other files there like META-INF/MANIFEST.MF as well as a pom.xml and pom.properties file. These come
standard with generation of a JAR in Maven. You can create your own manifest if you choose, but Maven will
generate one by default if you don't. (You can also modify the entries in the default manifest. We will touch on
this later.) The pom.xml and pom.properties files are packaged up in the JAR so that each artifact produced
by Maven is self-describing and also allows you to utilize the metadata in your own application if the need
arises. One simple use might be to retrieve the version of your application. Operating on the POM file would
require you to use some Maven utilities but the properties can be utilized using the standard Java API and look
like the following:
#Generated by Maven
#Tue Oct 04 15:43:21 GMT-05:00 2005
version=1.0-SNAPSHOT
groupId=com.mycompany.app
artifactId=my-app
To add resources to the classpath for your unit tests, you follow the same pattern as you do for adding
resources to the JAR except the directory you place resources in is ${project.basedir}/src/test/resources .
At this point you would have a project directory structure that would look like the following:
my-app
|-- pom.xml
`-- src
|-- main
| |-- java
| | `-- com
| | `-- mycompany
| | `-- app
| | `-- App.java
| `-- resources
| `-- META-INF
| |-- application.properties
`-- test
|-- java
| `-- com
| `-- mycompany
| `-- app
| `-- AppTest.java
`-- resources
`-- test.properties
In a unit test you could use a simple snippet of code like the following to access the resource required for
testing:
1. ...
2.
3. // Retrieve resource
4. InputStream is = getClass().getResourceAsStream( "/test.properties" );
5.
6. // Do something with the resource
7.
8. ...
To have Maven filter resources when copying, simply set filtering to true for the resource directory in your
pom.xml :
1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/200
1/XMLSchema-instance"
2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xs
d/maven-4.0.0.xsd">
>
3. <modelVersion>4.0.0<
</modelVersion>
4.
5. <groupId>com.mycompany.app<
</groupId>
6. <artifactId>my-app<
</artifactId>
7. <version>1.0-SNAPSHOT<
</version>
8. <packaging>jar<
</packaging>
9.
10. <name>Maven Quick Start Archetype<
</name>
11. <url>http://maven.apache.org<
</url>
12.
13. <dependencies>
14. <dependency>
15. <groupId>junit<
</groupId>
16. <artifactId>junit<
</artifactId>
17. <version>4.11<
</version>
18. <scope>test<
</scope>
19. </dependency>
20. </dependencies>
21.
22. <build>
23. <resources>
24. <resource>
25. <directory>src/main/resources<
</directory>
26. <filtering>true<
</filtering>
27. </resource>
28. </resources>
29. </build>
30. </project>
You'll notice that we had to add the build , resources , and resource elements which weren't there before.
In addition, we had to explicitly state that the resources are located in the src/main/resources directory. All of
this information was provided as default values previously, but because the default value for filtering is false,
we had to add this to our pom.xml in order to override that default value and set filtering to true.
To reference a property defined in your pom.xml , the property name uses the names of the XML elements that
define the value, with "pom" being allowed as an alias for the project (root) element. So ${project.name}
refers to the name of the project, ${project.version} refers to the version of the project,
${project.build.finalName} refers to the final name of the file created when the built project is packaged,
etc. Note that some elements of the POM have default values, so don't need to be explicitly defined in your
pom.xml for the values to be available here. Similarly, values in the user's settings.xml can be referenced
using property names beginning with "settings" (for example, ${settings.localRepository} refers to the path
of the user's local repository).
To continue our example, let's add a couple of properties to the application.properties file (which we put in
the src/main/resources directory) whose values will be supplied when the resource is filtered:
# application.properties
application.name=${project.name}
application.version=${project.version}
With that in place, you can execute the following command (process-resources is the build lifecycle phase
where the resources are copied and filtered):
mvn process-resources
and the application.properties file under target/classes (and will eventually go into the jar) looks like this:
# application.properties
application.name=Maven Quick Start Archetype
application.version=1.0-SNAPSHOT
To reference a property defined in an external file, all you need to do is add a reference to this external file in
your pom.xml . First, let's create our external properties file and call it src/main/filters/filter.properties :
# filter.properties
my.filter.value=hello!
# application.properties
application.name=${project.name}
application.version=${project.version}
message=${my.filter.value}
the next execution of the mvn process-resources command will put our new property value into
application.properties . As an alternative to defining the my.filter.value property in an external file, you could
also have defined it in the properties section of your pom.xml and you'd get the same effect (notice I don't
need the references to src/main/filters/filter.properties either):
Filtering resources can also get values from system properties; either the system properties built into Java (like
java.version or user.home ) or properties defined on the command line using the standard Java -D
parameter. To continue the example, let's change our application.properties file to look like this:
# application.properties
java.version=${java.version}
command.line.prop=${command.line.prop}
Now, when you execute the following command (note the definition of the command.line.prop property on the
command line), the application.properties file will contain the values from the system properties.
The dependencies section of the pom.xml lists all of the external dependencies that our project needs in order
to build (whether it needs that dependency at compile time, test time, run time, or whatever). Right now, our
project is depending on JUnit only (I took out all of the resource filtering stuff for clarity):
For each external dependency, you'll need to define at least 4 things: groupId, artifactId, version, and scope.
The groupId, artifactId, and version are the same as those given in the pom.xml for the project that built that
dependency. The scope element indicates how your project uses that dependency, and can be values like
compile , test , and runtime . For more information on everything you can specify for a dependency, see the
Project Descriptor Reference (/ref/current/maven-model/maven.html).
For more information about the dependency mechanism as a whole, see Introduction to Dependency
Mechanism (../introduction/introduction-to-dependency-mechanism.html).
With this information about a dependency, Maven will be able to reference the dependency when it builds the
project. Where does Maven reference the dependency from? Maven looks in your local repository
( ${user.home}/.m2/repository is the default location) to find all dependencies. In a previous section, we
installed the artifact from our project (my-app-1.0-SNAPSHOT.jar) into the local repository. Once it's installed
there, another project can reference that jar as a dependency simply by adding the dependency information to
its pom.xml :
What about dependencies built somewhere else? How do they get into my local repository? Whenever a project
references a dependency that isn't available in the local repository, Maven will download the dependency from a
remote repository into the local repository. You probably noticed Maven downloading a lot of things when you
built your very first project (these downloads were dependencies for the various plugins used to build the
project). By default, the remote repository Maven uses can be found (and browsed) at https://
repo.maven.apache.org/maven2/ (https://repo.maven.apache.org/maven2/). You can also set up your own
remote repository (maybe a central repository for your company) to use instead of or in addition to the default
remote repository. For more information on repositories you can refer to the Introduction to Repositories (../
introduction/introduction-to-repositories.html).
Let's add another dependency to our project. Let's say we've added some logging to the code and need to add
log4j as a dependency. First, we need to know what the groupId, artifactId, and version are for log4j. The
appropriate directory on Maven Central is called /maven2/log4j/log4j (https://repo.maven.apache.org/maven2/
log4j/log4j/). In that directory is a file called maven-metadata.xml. Here's what the maven-metadata.xml for log4j
looks like:
1. <metadata>
2. <groupId>log4j<
</groupId>
3. <artifactId>log4j<
</artifactId>
4. <version>1.1.3<
</version>
5. <versioning>
6. <versions>
7. <version>1.1.3<
</version>
8. <version>1.2.4<
</version>
9. <version>1.2.5<
</version>
10. <version>1.2.6<
</version>
11. <version>1.2.7<
</version>
12. <version>1.2.8<
</version>
13. <version>1.2.11<
</version>
14. <version>1.2.9<
</version>
15. <version>1.2.12<
</version>
16. </versions>
17. </versioning>
18. </metadata>
From this file, we can see that the groupId we want is "log4j" and the artifactId is "log4j". We see lots of different
version values to choose from; for now, we'll just use the latest version, 1.2.12 (some maven-metadata.xml files
may also specify which version is the current release version: see repository metadata reference (/ref/current/
maven-repository-metadata/repository-metadata.html)). Alongside the maven-metadata.xml file, we can see a
directory corresponding to each version of the log4j library. Inside each of these, we'll find the actual jar file (e.g.
log4j-1.2.12.jar) as well as a pom file (this is the pom.xml for the dependency, indicating any further
dependencies it might have and other information) and another maven-metadata.xml file. There's also an md5
file corresponding to each of these, which contains an MD5 hash for these files. You can use this to authenticate
the library or to figure out which version of a particular library you may be using already.
Now that we know the information we need, we can add the dependency to our pom.xml:
1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/200
1/XMLSchema-instance"
2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xs
d/maven-4.0.0.xsd">
>
3. <modelVersion>4.0.0<
</modelVersion>
4.
5. <groupId>com.mycompany.app<
</groupId>
6. <artifactId>my-app<
</artifactId>
7. <version>1.0-SNAPSHOT<
</version>
8. <packaging>jar<
</packaging>
9.
10. <name>Maven Quick Start Archetype<
</name>
11. <url>http://maven.apache.org<
</url>
12.
13. <dependencies>
14. <dependency>
15. <groupId>junit<
</groupId>
16. <artifactId>junit<
</artifactId>
17. <version>4.11<
</version>
18. <scope>test<
</scope>
19. </dependency>
20. <dependency>
21. <groupId>log4j<
</groupId>
22. <artifactId>log4j<
</artifactId>
23. <version>1.2.12<
</version>
24. <scope>compile<
</scope>
25. </dependency>
26. </dependencies>
27. </project>
Now, when we compile the project ( mvn compile ), we'll see Maven download the log4j dependency for us.
Note that if you are connecting to an openssh ssh server which has the parameter "PasswordAuthentication" set
to "no" in the sshd_config, you will have to type your password each time for username/password
authentication (although you can log in using another ssh client by typing in the username and password). You
might want to switch to public key authentication in this case.
Care should be taken if using passwords in settings.xml . For more information, see Password Encryption (../
mini/guide-encryption.html).
mvn archetype:generate \
-DarchetypeGroupId=org.apache.maven.archetypes \
-DarchetypeArtifactId=maven-archetype-site \
-DgroupId=com.mycompany.app \
-DartifactId=my-app-site
Now head on over to the Guide to creating a site (../mini/guide-site.html) to learn how to create the
documentation for your project.
mvn archetype:generate \
-DarchetypeGroupId=org.apache.maven.archetypes \
-DarchetypeArtifactId=maven-archetype-webapp \
-DgroupId=com.mycompany.app \
-DartifactId=my-webapp
Note that these must all be on a single line. This will create a directory called my-webapp containing the
following project descriptor:
1. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/200
1/XMLSchema-instance"
2. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xs
d/maven-4.0.0.xsd">
>
3. <modelVersion>4.0.0<
</modelVersion>
4.
5. <groupId>com.mycompany.app<
</groupId>
6. <artifactId>my-webapp<
</artifactId>
7. <version>1.0-SNAPSHOT<
</version>
8. <packaging>war<
</packaging>
9.
10. <dependencies>
11. <dependency>
12. <groupId>junit<
</groupId>
13. <artifactId>junit<
</artifactId>
14. <version>4.11<
</version>
15. <scope>test<
</scope>
16. </dependency>
17. </dependencies>
18.
19. <build>
20. <finalName>my-webapp<
</finalName>
21. </build>
22. </project>
Note the <packaging> element - this tells Maven to build as a WAR. Change into the webapp project's
directory and try:
mvn package
You'll see target/my-webapp.war is built, and that all the normal steps were executed.
Firstly, we need to add a parent pom.xml file in the directory above the other two, so it should look like this:
+- pom.xml
+- my-app
| +- pom.xml
| +- src
| +- main
| +- java
+- my-webapp
| +- pom.xml
| +- src
| +- main
| +- webapp
We'll need a dependency on the JAR from the webapp, so add this to my-webapp/pom.xml :
1. ...
2. <dependencies>
3. <dependency>
4. <groupId>com.mycompany.app</groupId>
5. <artifactId>my-app</artifactId>
6. <version>1.0-SNAPSHOT</version>
7. </dependency>
8. ...
9. </dependencies>
Finally, add the following <parent> element to both of the other pom.xml files in the subdirectories:
mvn verify
The WAR has now been created in my-webapp/target/my-webapp.war , and the JAR is included:
$ jar tvf my-webapp/target/my-webapp-1.0-SNAPSHOT.war
0 Fri Jun 24 10:59:56 EST 2005 META-INF/
222 Fri Jun 24 10:59:54 EST 2005 META-INF/MANIFEST.MF
0 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/
0 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/
0 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/my-webapp/
3239 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/my-webapp/pom.xml
0 Fri Jun 24 10:59:56 EST 2005 WEB-INF/
215 Fri Jun 24 10:59:56 EST 2005 WEB-INF/web.xml
123 Fri Jun 24 10:59:56 EST 2005 META-INF/maven/com.mycompany.app/my-webapp/pom.proper
ties
52 Fri Jun 24 10:59:56 EST 2005 index.jsp
0 Fri Jun 24 10:59:56 EST 2005 WEB-INF/lib/
2713 Fri Jun 24 10:59:56 EST 2005 WEB-INF/lib/my-app-1.0-SNAPSHOT.jar
How does this work? Firstly, the parent POM created (called app ), has a packaging of pom and a list of
modules defined. This tells Maven to run all operations over the set of projects instead of just the current one (to
override this behaviour, you can use the --non-recursive command line option).
Next, we tell the WAR that it requires the my-app JAR. This does a few things: it makes it available on the
classpath to any code in the WAR (none in this case), it makes sure the JAR is always built before the WAR, and
it indicates to the WAR plugin to include the JAR in its library directory.
You may have noticed that junit-4.11.jar was a dependency, but didn't end up in the WAR. The reason for
this is the <scope>test</scope> element - it is only required for testing, and so is not included in the web
application as the compile time dependency my-app is.
The final step was to include a parent definition. This ensures that the POM can always be located even if the
project is distributed separately from its parent by looking it up in the repository.