Maven has a command for starting a project:
mvn archetype:create \
— DgroupId=com.techmaine \
— DartifactId=demo-mvn \
— DpackageName=com.techmaine.mvndemo \
— Dversion=1.0
Plugin Name
mvn archetype :create \
— DgroupId=com.techmaine \
— DartifactId=demo-mvn \
— DpackageName=com.techmaine.mvndemo \
— Dversion=1.0
Plugin Name
Goal
mvn archetype :create \
— DgroupId=com.techmaine \
— DartifactId=demo-mvn \
— DpackageName=com.techmaine.mvndemo \
— Dversion=1.0
Voila! Look what maven has done for you:
<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>com.techmaine</groupId>
<artifactId>demo-mvn</artifactId>
<packaging>jar</packaging>
<version>1.0</version>
<name>demo-mvn</name>
<url>http://maven.apache.org</url>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>3.8.1</version>
<scope>test</scope>
</dependency>
</dependencies> ⇦ We'll add the dependency here.
</project>
This is all we need to add:
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-annotations</artifactId>
<version>3.3.1.ga</version>
</dependency>
We don't need to tell Maven about any of the jars on which Hibernate depends; Maven takes care of all of the transitive dependencies for us!
STUPIDITY ALERT!
Maven assumes a default source version of 1.3. We need to tell it if we want 1.5. Here's a preview of plugin configuration:
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.0.2</version>
<configuration>
<source>1.5</source>
<target>1.5</target>
</configuration>
</plugin>
</plugins>
</build>
Create a resources directory beneath the main (and, optionally, test) directory, and put the Hibernate configuration file there.
Next, package everything up before we run it.
To do this, invoke maven thusly :
mvn packageThis is an alternate way to invoke maven. Instead of specifying a plugin and goal, you specify a phase (in this case, package is the phase). A phase is a sequenced set of goals. The package phase compiles the java classes and copies the resources
Next, use the exec plugin to run our application:
mvn exec:exec \
– DmainClass=com.techmaine.mvndemo.App
We told maven
ANT
We downloaded jars and dependencies ourselvesWe told maven
When you first download it, almost nothing!
* Actually, dependency downloads are done by a plugin, too..
But... from where?
<project xmlns=http://maven.apache.org/POM/4.0.0 >
<modelVersion>4.0.0</modelVersion>
<groupId>com.techmaine</groupId>
<artifactId>superduper</artifact>
<packaging>jar</packaging>
<version>1.0.0</version>
<name>Super Duper Amazing Deluxe Project</name>
<modules>
<!-- Sub-modules of this project -->
</modules>
<parent>
<!-- Parent POM stuff if applicable -->
</parent>
<properties>
<!-- Ad-hoc properties used in the build -->
</properties>
<dependencies>
<!-- Dependency Stuff -->
</dependencies>
<build>
<!-- Build Configuration -->
<plugins>
<!-- plugin configuration -->
</plugins>
</build>
<profiles>
<!-- build profiles -->
</profiles>
</project>
<project xmlns=http://maven.apache.org/POM/4.0.0 >
<modelVersion>4.0.0</modelVersion>
<name>Super Duper Amazing Deluxe Project</name>
<packaging>jar</packaging>
<groupId>com.techmaine</groupId>
<artifactId>superduper</artifact>
<version>1.0.0</version>
<modules>
<!-- Sub-modules of this project -->
</modules>
<parent>
<!-- Parent POM stuff if applicable -->
</parent>
<properties>
<!-- Ad-hoc properties used in the build -->
</properties>
<dependencies>
<!-- Dependency Stuff -->
</dependencies>
<build>
<!-- Build Configuration -->
<plugins>
<!-- plugin configuration -->
</plugins>
</build>
<profiles>
<!-- build profiles -->
</profiles>
</project>
<project xmlns=http://maven.apache.org/POM/4.0.0 >
<modelVersion>4.0.0</modelVersion>
<name>Super Duper Amazing Deluxe Project</name>
<packaging>jar</packaging>
<groupId>com.techmaine</groupId>
<artifactId>superduper</artifact>
<version>1.0.0</version>
<parent>
<!-- Parent POM stuff if applicable -->
</parent>
<modules>
<!-- Sub-modules of this project -->
</modules>
<properties>
<!-- Ad-hoc properties used in the build -->
</properties>
<dependencies>
<!-- Dependency Stuff -->
</dependencies>
<build>
<!-- Build Configuration -->
<plugins>
<!-- plugin configuration -->
</plugins>
</build>
<profiles>
<!-- build profiles -->
</profiles>
</project>
What is inherited ?
Why Inherit ?
<project xmlns=http://maven.apache.org/POM/4.0.0 >
<modelVersion>4.0.0</modelVersion>
<name>Super Duper Amazing Deluxe Project</name>
<packaging>jar</packaging>
<groupId>com.techmaine</groupId>
<artifactId>superduper</artifact>
<version>1.0.0</version>
<parent>
<!-- Parent POM stuff if applicable -->
</parent>
<modules>
<!-- Sub-modules of this project -->
</modules>
<properties>
<!-- Ad-hoc properties used in the build -->
</properties>
<dependencies>
<!-- Dependency Stuff -->
</dependencies>
<build>
<!-- Build Configuration -->
<plugins>
<!-- plugin configuration -->
</plugins>
</build>
<profiles>
<!-- build profiles -->
</profiles>
</project>
<project xmlns=http://maven.apache.org/POM/4.0.0 >
<modelVersion>4.0.0</modelVersion>
<name>Super Duper Amazing Deluxe Project</name>
<packaging>jar</packaging>
<groupId>com.techmaine</groupId>
<artifactId>superduper</artifact>
<version>1.0.0</version>
<parent>
<!-- Parent POM stuff if applicable -->
</parent>
<modules>
<!-- Sub-modules of this project -->
</modules>
<properties>
<!-- Ad-hoc properties used in the build -->
</properties>
<dependencies>
<!-- Dependency Stuff -->
</dependencies>
<build>
<!-- Build Configuration -->
<plugins>
<!-- plugin configuration -->
</plugins>
</build>
<profiles>
<!-- build profiles -->
</profiles>
</project>
User-Defined properties are like ant properties:
<properties>
<hibernate.version>3.3.0.ga</hibernate.version>
</properties>
...
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate</artifact>
<version>${hibernate.version}</version>
</dependency>
</dependencies>
<project xmlns=http://maven.apache.org/POM/4.0.0 >
<modelVersion>4.0.0</modelVersion>
<name>Super Duper Amazing Deluxe Project</name>
<packaging>jar</packaging>
<groupId>com.techmaine</groupId>
<artifactId>superduper</artifact>
<version>1.0.0</version>
<parent>
<!-- Parent POM stuff if applicable -->
</parent>
<modules>
<!-- Sub-modules of this project -->
</modules>
<properties>
<!-- Ad-hoc properties used in the build -->
</properties>
<dependencies>
<!-- Dependency Stuff -->
</dependencies>
<build>
<!-- Build Configuration -->
<plugins>
<!-- plugin configuration -->
</plugins>
</build>
<profiles>
<!-- build profiles -->
</profiles>
</project>
Maven's piece de resistance
<dependencies>
<dependency>
<groupId>com.techmaine</groupId>
<artifactId>awesome-lib</artifactId>
<version>1.3.5</version>
<scope>compile</scope>
<optional>false</optional>
</dependency>
</dependencies>
groupId and artifactId: must be unique
<dependencies>
<dependency>
<groupId>com.techmaine</groupId>
<artifactId>awesome-lib</artifactId>
<version>1.3.5</version>
<scope>compile</scope>
<optional>false</optional>
</dependency>
</dependencies>
<dependencies>
<dependency>
<groupId>com.techmaine</groupId>
<artifactId>awesome-lib</artifactId>
<version>1.3.5</version>
<scope>compile</scope>
<optional>false</optional>
</dependency>
</dependencies>
<dependencies>
<dependency>
<groupId>com.techmaine</groupId>
<artifactId>awesome-lib</artifactId>
<version>1.3.5</version>
<scope>compile</scope>
<optional>false</optional>
</dependency>
</dependencies>
<dependencies>
<dependency>
<groupId>com.techmaine</groupId>
<artifactId>awesome-lib</artifactId>
<version>1.3.5</version>
<scope>compile</scope>
<optional>false</optional>
</dependency>
</dependencies>
Prevents this dependency from being included as a transitive dependency if some other project depends on this project.
Our project (Project "A") depends on B and C. Project C depends on projects D and E. Thus, our project depends on B, C, D, and E, and Maven will fetch and use these artifacts appropriately.
Now, let's say project C has a dependency on project B, but requires version 1.1. If project A's POM doesn't explicitly require version 1.0 or earlier, then Maven will choose version 1.1.
Uh oh. Now Project A is saying that it must use version 1.0 of B, and only version 1.0, and project C needs version 1.1 of project B.
<dependencies>
<dependency>
<groupId>com.techmaine</groupId>
<artifactId>project-b</artifactId>
<version>[1.0]</version>
</dependency>
<dependency>
<groupId>com.techmaine</groupId>
<artifactId>project-c</artifactId>
<exclusions>
<exclusion>
<groupId>com.techmaine</groupId>
<artifactId>project-b</artifactId>
</exclusion>
</exclusions>
</dependency>
</dependencies>
The dependencyManagement element allows you to specify version numbers of dependencies in child POMs without making all children dependent on a particular library.
Parent POM
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
<version>2.5.5</version>
</dependency>
</dependencies>
</dependencyManagement>
Child POM
<dependencies>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring</artifactId>
</dependency>
</dependencies>
<project xmlns=http://maven.apache.org/POM/4.0.0 >
<modelVersion>4.0.0</modelVersion>
<name>Super Duper Amazing Deluxe Project</name>
<packaging>jar</packaging>
<groupId>com.techmaine</groupId>
<artifactId>superduper</artifact>
<version>1.0.0</version>
<parent>
<!-- Parent POM stuff if applicable -->
</parent>
<modules>
<!-- Sub-modules of this project -->
</modules>
<properties>
<!-- Ad-hoc properties used in the build -->
</properties>
<dependencies>
<!-- Dependency Stuff -->
</dependencies>
<build>
<!-- Build Configuration -->
<plugins>
<!-- plugin configuration -->
</plugins>
</build>
<profiles>
<!-- build profiles -->
</profiles>
</project>
<project>
...
<build>
<filters>
<filter>filter/my.properties</filter>
</filters>
<resources>
...
</resources>
<plugins>
...
</plugins>
</build>
...
</project>
<project>
...
<build>
<filters>
<filter>filter/my.properties</filter>
</filters>
<resources>
...
</resources>
<plugins>
...
</plugins>
</build>
...
</project>
Path to a properties file (name=value). When the resources are processed during packaging, maven will substitute any ${name} strings with the corresponding value from the properties file.
<resources>
<resource>
<directory>src/main/scripts</directory>
<filtering>true</filtering>
<targetPath>bin</targetPath>
<includes>
<include>run.bat</include>
<include>run.sh</include>
</includes>
<resource>
</resources>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>2.2</version>
<configuration>
<!-- Configuration details go here -->
</configuration>
</plugin>
</plugins>
</build>
Below, we have configured the clean plugin to delete files ending in .txt from the tmp directory
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-clean-plugin</artifactId>
<version>2.2</version>
<configuration>
<filesets>
<fileset>
<directory>tmp</directory>
<includes>
<include>**/*.txt</include>
</includes>
<followSymlinks>false</followSymlinks>
</fileset>
</filesets>
</configuration>
</plugin>
</plugins>
</build>
Maven supports three standard lifecycles
The Clean Lifecycle has three phases:
Only clean is "bound" by default, to the clean goal of the clean plugin. You can bind other tasks using executions.
Let's say you have a whizz-bang plugin named mp3, and it has a goal named play that lets you play an arbitrary audio clip, and you'd like to play a clip during pre-clean:
<plugin>
<groupId>com.techmaine</groupId>
<artifactId>mp3</artifactId>
<version>1.0</version>
<executions>
<execution>
<phase>pre-clean</phase>
<goals>
<goal>play</goal>
</goals>
<configuration>
<audioClipFile>toilet-flush.mp3</audioClipFile>
</configuration>
</execution>
</executions>
</plugin>
Maven models the software build process with the 21 step "default lifecycle"
Maven automatically binds goals to the phases on the previous slide based on the packaging type. E.g., for projects that package WARs:
<project xmlns=http://maven.apache.org/POM/4.0.0 >
<modelVersion>4.0.0</modelVersion>
<name>Super Duper Amazing Deluxe Project</name>
<packaging>jar</packaging>
<groupId>com.techmaine</groupId>
<artifactId>superduper</artifact>
<version>1.0.0</version>
<parent>
<!-- Parent POM stuff if applicable -->
</parent>
<modules>
<!-- Sub-modules of this project -->
</modules>
<properties>
<!-- Ad-hoc properties used in the build -->
</properties>
<dependencies>
<!-- Dependency Stuff -->
</dependencies>
<build>
<!-- Build Configuration -->
<plugins>
<!-- plugin configuration -->
</plugins>
</build>
<profiles>
<!-- build profiles -->
</profiles>
</project>
Sometimes our artifacts need to be tweaked for different "customers"
In the POM itself, in an external profiles.xml file, or even in settings.xml
<project>
...
<profiles>
<profile>
<id>appserverConfig-dev</id>
<properties>
<appserver.home>/path/to/dev/appserver</appserver.home>
</properties>
</profile>
<profile>
<id>appserverConfig-dev-2</id>
<properties>
<appserver.home>/path/to/another/dev/appserver2</appserver.home>
</properties>
</profile>
</profiles>
...
</project>
You can even configure plugins based on a profile:
<project>
...
<profiles>
<profile>
<id>production</id>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<debug>false</debug>
<optimize>true</optimize>
</configuration>
</plugin>
</plugins>
<appserver.home>/path/to/dev/appserver</appserver.home>
</build>
</profile>
...
<settings>
...
<activeProfiles>
<activeProfile>dev</activeProfile>
</activeProfiles>
...
</settings>
<project>
...
<profiles>
<profile>
<id>dev</id>
<activation>
<activeByDefault>false</activeByDefault>
<jdk>1.5</jdk>
<os>
<name>Windows XP</name>
<family>Windows</famliy>
<arch>x86</arch>
<version>5.1.2600</version>
</os>
<property>
<name>mavenVersion</name>
<value>2.0.9</value>
</property>
<file>
<exists>file2.properties</exists>
<missing>file1.properties</missing>
</file>
</activation>
...
</profile>
</profiles>
</project>
...returns "about 128,000" results
Maven builds recursively, using nested <modules/> Can be tweaked by maven parameters