Sunday, March 1, 2020

Getting Started with Maven

Since Ant, Maven, and Gradle are dominated in the JVM ecosystem as  Java build automation tools, you may be familiar with Maven If you have ever worked on a Java Project.

Let’s explore how these Java build automation tools evolved in the JVM ecosystem.

  • Apache Ant (“Another Neat Tool”) is a Java library which is used to automate the build processes for Java applications. Other than that it can be used for building non-Java applications.
  • Apache Maven is a build automation tool and also a dependency management tool. It is primarily used for Java applications. Maven also uses XML files the same as Apache Ant but in a much more manageable way.
  • Gradle is a dependency management and a build automation tool which was built upon the concepts of Ant and Maven.

In this article, I am going to discuss Maven as a dependency management tool. 





Philosophy of Maven


Maven was born at the Apache Software Foundation in order to make several projects in the same manner. That makes it easier for the developers to move between several projects since they have a clear idea about how all projects are working by understanding a single project.  It's not only about implementation. The same idea extends to testing, generating documentation and reports, testing and deploying. 

Maven is trying to apply patterns to a project's build infrastructure in order to promote productivity and comprehension using standard conventions and best practices. 


Installing Apache Maven


You can download the ready-made binary distribution archive from here and install it on your machine according to these steps


Create your first Maven project


Here I am going to create the project using Maven's archetype mechanism. An archetype is defined as an original pattern or model which used to make all the things in the same manner.  It delivers a Maven project with the user's requirements by combining user inputs with the project template.


You can create a simple  Maven project  by executing the following  code snippet in the command line:


mvn -B archetype:generate \
  -DarchetypeGroupId=org.apache.maven.archetypes \
  -DgroupId=com.mycompany.app \
  -DartifactId=my-app


This will create the maven project inside a directory named my-app with the following directory structure. 


This is the standard layout for Maven projects. Here
  • The application sources reside in ${basedir}/src/main/java 
  • Test sources reside in ${basedir}/src/test/java
 where ${basedir} represents the directory containing pom.xml


my-app directory structure


|-- pom.xml
`-- src
    |-- main
    |   `-- java
    |       `-- com
    |           `-- mycompany
    |               `-- app
    |                   `-- App.java
    `-- test
        `-- java
            `-- com
                `-- mycompany
                    `-- app
                        `-- AppTest.java



Introduction to the POM


Inside the my-app directory, it contains the pom.xml which is the Project Object Model (POM) for this maven project.  POM contains every important piece of information about the Maven project. 

Following is a copy of the pom.xml in the created Maven project.


<projectxmlns="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.mycompany.app</groupId>
  <artifactId>my-app</artifactId>
  <packaging>jar</packaging>
  <version>1.0-SNAPSHOT</version>
  <name>my-app</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>
</project>


This includes the key elements every POM contains. Le’s consider the top-level element in all Maven pom.xml files.


modelVersion
  • The version of the object model

groupId
  • The unique identifier of the organization or group that created the project.
  • It is based on the fully qualified domain name of the organization
  • One of the key identifiers of a project
  • Will be used when creating the directory structure
  • In the project we created, groupId is “com.mycompany.app”. So subdirectories were created under the main directory according to the groupId.
        -- src
          |-- main
          |   `-- java
          |       `-- com
          |           `-- mycompany
          |               `-- app


artifactId -
  • Indicates the unique base name of the primary artifact being generated by the project
  • The primary artifact for a project is typically a JAR file. Secondary artifacts like source bundles also use the artifactId as part of their final name. 
  • A typical artifact produced by Maven would be the following format      
    •    <artifactId>-<version>.<extension> (for example, myapp-1.0.jar)
  • Project main directory is created with artifactId as its name

packaging -
  • Indicates the package type (e.g. JAR, WAR, EAR, etc) to be used by the artifact
  • Indicate a specific lifecycle to use as part of the build process
  • The default value is JAR and you don’t have to specify this for most projects


version -
  • Indicates the version of the artifact generated by the project
  • Sometimes the version has the suffix: -SNAPSHOT (ex- 2.0-SNAPSHOT). It refers to the 'latest' code along a development branch and provides no guarantee the code is stable or unchanging. version 2.0-SNAPSHOT is released as version 2.0, and the new development version is version 2.1-SNAPSHOT

name -
  •  Indicates the display name used for the project 
  • Used in Maven's generated documentation

url
  • Indicates where the project's site can be found
  • Used in Maven's generated documentation


description -
  •  Provides a basic description of the project
  • Used in Maven's generated documentation



Maven Build Lifecycle 




Maven is based around the central concept of a build lifecycle. It clearly defines the process of building and distributing a particular artifact (project).


There are three built-in build lifecycles named as default, clean and site.,


The default lifecycle handles your project deployment. Following lifecycle phases needs to be executed sequentially to complete the default lifecycle.

  • validate - Validate the project is correct and all necessary information is available
  • compile - Compile the source code of the project
  • test - Test the compiled source code using a suitable unit testing framework. These tests should not require the code be packaged or deployed
  • package - Take the compiled code and package it in its distributable format, such as a JAR.
  • verify - Run any checks on results of integration tests to ensure quality criteria are met
  • install - Install the package into the local repository, for use as a dependency in other projects locally
  • deploy - Done in the build environment, copies the final package to the remote repository for sharing with other developers and projects.


The clean life cycle handles project cleaning. It removes the target directory with all the build data before starting so that it is fresh.

The site lifecycle handles the creation of the project's site documentation.

 

Add resources to JAR and filtering values 





You can place any resources in the ${basedir}/src/main/resources directory which wish to package inside the JAR. Any files placed within that directory are packaged in the JAR with the exact structure starting at the base of the JAR.  You can place a application.properties file within that directory

You may have a requirement to give values for the variables in the resource file at build time. You can do that by putting a reference to the variable in the resource file using the ${<property name>} syntax. The property can be one of the values defined in 

  • pom.xml
  • A value defined in the user’s properties.xml 
  • A property defined in an external properties file
  • System property


To have Maven filter resources when copying, You have to add the following elements to the pom.xml. 



<build>
    <resources>
      <resource>
        <directory>src/main/resources</directory>
        <filtering>true</filtering>
      </resource>
    </resources>
</build>



Then you can reference variables defined in pom.xml as follows.

 ${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


Ex -

The application.properties file under ${basedir}/src/main/resources


# application.properties 

application.name=${project.name}
application.version=${project.version}


The application.properties file under target/classes after executing the mvn process-resources command  which is the build lifecycle phase where the resources are copied and filtered. 


# application.properties

application.name=my-app
application.version=1.0-SNAPSHOT


Build more than one project at once





Maven has the ability to deal with multiple modules. Consider following as the multi-module directory structure. In that base directory contains two subdirectories as my-app and my-webapp and also parent pom.xml file.


+- pom.xml
+- my-app
| +- pom.xml
| +- src
|   +- main
|     +- java
+- my-webapp
| +- pom.xml
| +- src
|   +- main
|     +- java



Here, the parent pom.xml file should mention its modes as follows



<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/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>com.mycompany.app</groupId>
  <artifactId>app</artifactId>
  <version>1.0-SNAPSHOT</version>
  <packaging>pom</packaging>  
  <modules>
    <module>my-app</module>
    <module>my-webapp</module>
  </modules>
</project>


And modules need to mention their parent in their pom.xml files as follows

 <parent>
    <groupId>com.mycompany.app</groupId>
    <artifactId>app</artifactId>
    <version>1.0-SNAPSHOT</version>
  </parent>


Also, consider my-webapp requires the my-app JAR as a dependency. So it should mention inside my-webapp/pom.xml as follows.


<dependencies>
    <dependency>
      <groupId>com.mycompany.app</groupId>
      <artifactId>my-app</artifactId>
      <version>1.0-SNAPSHOT</version>
    </dependency>
    ...
</dependencies>



When you run mvn install command the WAR file is created in my-webapp/target directory including the JAR file. Here JAR is always built before the WAR and it indicates to the WAR plugin to include the JAR in its library directory.


Maven is a part of the Apache Software Foundation. It includes many features to simplifies the software development life cycle. 























No comments:

Post a Comment

How to send Slack notification using a Python script?

 In this article,  I am focussing on sending Slack notifications periodically based on the records in the database. Suppose we have to monit...