Welcome back to the second part of our tutorial-series on Maven 2. This part will focus on the pom.xml and the Maven 2 dependency management, Maven properties and dependency scopes. To get started let’s first set up a project similar to the project we used in the first part of this tutorial. Set up the project as described in the article Maven 2 (Part 1): Setting up a simple Apache Maven 2 Project and reopen the pom.xml.
Dependencies
Some dependencies often are needed to write your applications. Commonly we (developers, developers, developers,…) are using some open source libraries and frameworks (e.g. the spring application framework or apache commons-logging,…). Sometimes own libraries should be referenced by a java project. To solve this problem Maven delivers a very good dependency mechanism that manages the dependencies of your project transitivly.
If you run
mvn package
Maven will download all dependencies referenced by your pom.xml from the central Maven 2 repository automatically. On mvnrepository.com you are able to search over all dependencies provided by this repository. Sometimes dependencies you need are not provided by the default Maven repository. In this case you don’t have to despair. Maven allows to set up and define own repositories aswell. We’ll explain how to set up own repositories in a later part of this tutorial-series. Let’s first focus on dependencies and how to add them to your Maven 2 project by using apache commons-logging and the spring application framework.
We are going to start with apache commons-logging. To add apache commons-logging we add the following xml-nodes to our project:
<project xmlns="http://maven.apache.org/POM/4.0.0" [...] > <modelVersion>4.0.0</modelVersion> <groupId>com.unitedcoders</groupId> <artifactId>MyExampleApp</artifactId> <packaging>jar</packaging> <version>0.0.1-SNAPSHOT</version> <name>MyExampleApp</name> <url>http://maven.apache.org</url> <dependencies> <!-- Apache commons-logging --> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.1.1</version> </dependency> <!-- Testing Dependencies --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.5</version> <scope>test</scope> </dependency> </dependencies> </project>
As you mentioned, we’ve done 2 changes. We changed the version number of junit to version 4.5 and we added a dependency node for commons-logging which contains groupId, artifactId and the version number. The groupId helps Maven to locate the dependency in the Maven repository. The artifactId defines which artifact of the specified group is needed (In our case “commons-logging”) and the “version”-node defines the exact version of the dependency. I think 1.1.1 is the latest version of commons-logging at this time. If you now run
mvn clean package
again you’ll see that Maven automatically downloads apache’s commons-logging-1.1.1.jar from http://repo*.maven.org. To get a little bit more confidant with this lets add some more dependencies by modifying our pom.xml like this:
<project xmlns="http://maven.apache.org/POM/4.0.0" [...] > <modelVersion>4.0.0</modelVersion> <groupId>com.unitedcoders</groupId> <artifactId>MyExampleApp</artifactId> <packaging>jar</packaging> <version>0.0.1-SNAPSHOT</version> <name>MyExampleApp</name> <url>http://maven.apache.org</url> <build> <finalName>MyExampleApp</finalName> <plugins> <plugin> <groupId>org.apache.maven.plugins</groupId> <artifactId>maven-compiler-plugin</artifactId> <pre class="prettyprint"> <source>1.5</source> <target>1.5</target> </configuration> </plugin> </plugins> </build> <dependencies> <!-- Spring Framework --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>2.5.5</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>2.5.5</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>2.5.5</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>2.5.5</version> </dependency> <!-- Apache commons-logging --> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>1.1.1</version> </dependency> <!-- javax Servlet API --> <dependency> <groupId>javax.servlet</groupId> <artifactId>servlet-api</artifactId> <version>2.4</version> <scope>provided</scope> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>jstl</artifactId> <version>1.1.2</version> </dependency> <dependency> <groupId>taglibs</groupId> <artifactId>standard</artifactId> <version>1.1.2</version> <scope>runtime</scope> </dependency> <!-- Testing Dependencies --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>4.5</version> <scope>test</scope> </dependency> <!-- Database --> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>1.2.2</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>5.1.6</version> </dependency> </dependencies> </project>
Please take a few minutes and take a look at all changes we made in pom.xml. After that let's discuss these changes starting at the top of pom.xml:
1. We added a build-node
The build-node contains build-specific configurations for our project. We inserted a "finalName" that defines how our jar-file will be named (in this case: MyExampleApp.jar) Also we added the „maven-compiler-plugin“ to be able to configure the Java version on which our project should be build.
2. Some more dependencies
And we added some more dependencies which we can use to set develop a web application for example.
Properties
Is there anything you don't like? Do you see anything that should be improved? Right. There are some redundant version numbers. That isn't very beautiful. We will now see a way to remove this redundancy: Properties. Take a look at the following example on how to use the maven property mechanism.
<project xmlns="http://maven.apache.org/POM/4.0.0" [...] > <modelVersion>4.0.0</modelVersion> <groupId>com.unitedcoders</groupId> <artifactId>MyExampleApp</artifactId> <packaging>jar</packaging> <version>0.0.1-SNAPSHOT</version> <name>MyExampleApp</name> <url>http://maven.apache.org</url> <build> [....] </build> <properties> <spring-version>2.5.5</spring-version> <junit-version>4.5</junit-version> <pre class="prettyprint">1.2.2</commons-dbcp-version> <pre class="prettyprint">1.1.1</commons-logging-version> </properties> <dependencies> <!-- Spring Framework --> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-core</artifactId> <version>${spring-version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>${spring-version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-web</artifactId> <version>${spring-version}</version> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-jdbc</artifactId> <version>${spring-version}</version> </dependency> <!-- Apache commons-logging --> <dependency> <groupId>commons-logging</groupId> <artifactId>commons-logging</artifactId> <version>${commons-logging-version}</version> </dependency> [....] <!-- Testing Dependencies --> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>${junit-version}</version> <scope>test</scope> </dependency> <!-- Database --> <dependency> <groupId>commons-dbcp</groupId> <artifactId>commons-dbcp</artifactId> <version>${commons-dbcp-version}</version> </dependency> [....] </dependencies> </project>
We've added the "properties"-node that contains our properties as subnodes. You are able to use these properties everywhere in your pom.xml by surrounding them with ${ and }. Especially on the spring dependencies you can see that the version-number-redundancy is gone. The version number is now defined only once. This isn't the biggest advantage ever and it doesn't seems to be rocket science, but I think it is good to define all versions at one position. Feel free to try out some own properties on all other dependency definitions.
Scopes
As you noticed i added a "scope"-node to some of the project's dependencies. The dependency scope defines to which part of the project's lifecycle the dependency is attached. For example the JUnit dependency is only added while running the tests. So i defined that this dependency is attached to the target "test".
There are at least 6 different scopes:
- compile: This scope indicates the Maven compilation phase. It is the default scope that will be used if no scope is defined.
- provided: This scope defines that this dependency is provided by the container (e.g. Apache Tomcat) at runtime.
- runtime: This scope indicates that this Dependency isn't required in the compilation phase but it is needed at runtime.
- test: "test"-dependencies are only while compiling and running the tests.
- system: This scope indicates that the dependency is provided by the system.
- import: "import" is only used in the pom's <dependencyManagement> section. It indicates that the specified POM should be replaced with the dependencies in that POM's <dependencyManagement> section.
For more informations on Maven 2 and how to configure eclipse to import Maven 2 projects please stay tuned. See ya... Phil
Previous Maven 2 articles:
Maven 2 (Part 1): Setting up a simple Apache Maven 2 Project
Further Maven 2 articles:
Maven 2 (Part 3): Configuring eclipse for Apache Maven 2 projects
Phillip Steffensen
Latest posts by Phillip Steffensen (see all)
- Conquer REST using curl - September 13, 2010
- Android: Dealing with ListActivities, customized ListAdapters and custom-designed items - July 14, 2010
- Developing a simple SOAP-webservice using Spring 3.0.1 and Apache CXF 2.2.6 - February 27, 2010