Friday, March 4, 2016

Apache Maven Notes.


Maven is not simply a build tool, it is a complete project management tool.


The Super POM

All Maven project POMs extend the Super POM, which defines a set of defaults shared by all projects. This Super POM is a part of the Maven installation.
The default Super POM defines a single remote Maven repository with an ID of central. This is the
Central Repository that all Maven clients are configured to read from by default.
This setting can be overridden by a custom settings.xml file.

$mvn help:effective-pom

Should print out an XML document capturing the merge between the Super POM and the current POM.


Version

Maven versions contain the following parts: 

<major version>.<minor version>.<incremental version>-<qualifier>
Maven versions can contain a string literal to signify that a project is currently under active development. If a version contains the string “-SNAPSHOT” then Maven will expand this token to a date and time value converted to UTC when you install or release this component. 

Eg. 

If your project has a version of “1.0-SNAPSHOT” and you deploy this project’s artifacts to a Maven repository, Maven would expand this version to “1.0-20080207-230803-1” if you were to deploy a release at 11:08 PM on February 7th, 2008 UTC. In other words, when you deploy a snapshot, you are not making a release of a software component.

If your project depends on a software component that is under active development, you can depend on a SNAPSHOT release, and Maven will periodically attempt to download the latest snapshot from a repository when you run a build.

Properties

3 implicit variables
  • env - The env variable exposes environment variables exposed by your operating system or shell.
  • project - The project variable exposes the POM. You can use a dot-notated (.) path to reference the value of a POM element.
  • settings - The settings variable exposes Maven settings information. You can use a dot-notated (.) path to reference the value of an element in a settings.xml file.
In addition to the three implicit variables, you can add custom properties set in the Maven POM or in a build profile.

<properties>
       <foo>bar</foo>
</properties> 


Dependencies

Eg.

<project>
...
   <dependencies>
      <dependency>
         <groupId>org.codehaus.xfire</groupId>
         <artifactId>xfire-java5</artifactId>
         <version>1.2.5</version>
     </dependency>
</dependencies>
...
</project>


Scopes

compile
compile is the default scope; compile dependencies are available in all classpaths, and they are packaged.

provided
provided dependencies are used when you expect the JDK or a container to provide them

runtime
runtime dependencies are required to execute and test the system, but they are not required for compilation. For example, you may need a JDBC API JAR at compile time and the JDBC driver implementation only at runtime.

test
test-scoped dependencies are not required during the normal operation of an application, and they are available only during test compilation and execution phases.

system
The system scope is similar to provided except that you have to provide an explicit path to the JAR on the local file system.

Optional Dependencies

You want this dependency for compile time but don't want other projects depending on your project to transitively get this dependency.

<dependency>
    <groupId>net.sf.ehcache</groupId>
    <artifactId>ehcache</artifactId>
    <version>1.4.1</version>
    <optional>true</optional>
</dependency>

Transitive Dependencies

Transitive Dependencies


Conflict Resolution

When you need to exclude a transitive dependency

<dependency>
   <groupId>org.sonatype.mavenbook</groupId>
   <artifactId>project-a</artifactId>
   <version>1.0</version>
   <exclusions>
      <exclusion>
         <groupId>org.sonatype.mavenbook</groupId>
         <artifactId>project-b</artifactId>
      </exclusion>
   </exclusions>
</dependency>

 

Dependency Management

You’ll usually see the dependencyManagement element in a top-level parent POM. Using the dependencyManagement element in a pom.xml allows you to reference a dependency in a child project without having to explicitly list the version. The dependencyManagement version is only used when the child does not declare a version directly.

Parent POM

<project>
   ...
   <artifactId>a-parent</artifactId>
   <dependencyManagement>
      <dependencies>
         <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.2</version>
            <scope>runtime</scope>
         </dependency>
      <dependencies>
   </dependencyManagement>


Child POM

<project>
 ...
 <parent>
  <groupId>...</groupId>
  <artifactId>a-parent</artifactId>
  <version>...</version>
 </parent>
 <artifactId>child-project</artifactId>
 ...
 <dependencies>
  <dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
  </dependency>
 </dependencies>
</project>


Items a Maven POM inherits from its parent POM:
  • identifiers (at least one of groupId or artifactId must be overridden.)
  • dependencies
  • developers and contributors
  • plugin lists
  • reports lists
  • plugin executions (executions with matching ids are merged)
  • plugin configuration

POM Packaging

If you have a set of dependencies which are logically grouped together. You can create a project with pom packaging that groups dependencies together.
Instead of having to include common dependencies in every project, you could create a special POM that does nothing more than to declare a set of common dependencies.
And then other projects depend on this.

<project>
 <groupId>com.maven.try</groupId>
 <artifactId>persistence-deps</artifactId>
 <version>1.0</version>
 <packaging>pom</packaging>
 <dependencies>
  <dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate</artifactId>
   <version>${hibernateVersion}</version>
  </dependency>
  <dependency>
   <groupId>org.springframework</groupId>
   <artifactId>spring-hibernate3</artifactId>
   <version>${springVersion}</version>
  </dependency>
  <dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <version>${mysqlVersion}</version>
  </dependency>
 </dependencies>
 <properties>
  <mysqlVersion>(5.1,)</mysqlVersion>
  <springVersion>(2.0.6,)</springVersion>
  <hibernateVersion>3.2.5.ga</hibernateVersion>
 </properties>
</project>

You can now add this project as a dependency and all of its dependencies will be added as transitive dependencies to your project. don’t forget to specify the dependency type as pom.

Build LifeCycle

There are three standard lifecycles in Maven:
  1. clean
  2. default (sometimes called build) 
  3. site.
Maven Default LifeCycle : Ref: Getting Started Apache Maven Video 


Plugins


<project>
 ...
<build>
<plugins>
 <plugin>
  <artifactId>maven-antrun-plugin</artifactId>
  <executions>
   <execution>
    <id>file-check-etc</id>
    <phase>comliple</phase> //optional, 
    //if not provided plugin's default phase is considered. 
    <goals>
     <goal>run</goal>
    </goals>
    <configuration>
     // plugins goal specific configuration
    </configuration>
   </execution>
  </executions>

 </plugin>
</plugins> 
</build>
</project>


Profiles

Maven allows you to define any number of build environments (build profiles) which can override any of the settings in the pom.xml.
Then you can run Maven with a command-line flag that tells Maven to execute goals in a specific profile.

<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>
  </build>
 </profile>
</profiles>


Each profile has to have an id element. This id element contains the name which is used to invoke this profile from the command-line. A profile is invoked by passing the 
-P<profile_id> command-line argument to Maven. 

The activation element lists the conditions for profile activation. we’ve specified that this profile will be activated by Java versions that begin with "1.6".


<profile>
 <id>jdk16</id>
  <activation>
                <activeByDefault>false</activeByDefault>
  <jdk>1.6</jdk>
 </activation>
 ...
</profile>