Recent Posts

Tuesday, 26 November 2019

Apache Maven Introduction


     Maven is a "Yiddish" [German language] word meaning "Accumulator of Knowledge". Maven was originally designed to simplify building processes in Jakarta Turbine project. There were several projects and each project contained slightly different ANT build files. JARs were checked into CVS.

     Apache group then developed Maven which can build multiple projects together, publish projects information, deploy projects, share JARs across several projects and help in the collaboration of teams. Apache Maven is a "Project Management Framework", it is much more than a simple Build tool, its declarative and standard approach simplifies many aspects of the Project Lifecycle.

The main Objective of MAVEN is
☀ A comprehensive model for projects, which is reusable, maintainable, and easier to comprehend [Understand].
☀ Plugins or tools that interact with this declarative model.

    MAVEN follows "Convention over Configuration" Principle, which means that developers are not required to create a build process themselves, Developers do not have to mention each and every configuration detail. Maven provides sensible default behavior for projects. MAVEN does the following activities of the project life cycle automatically.
☀ Provides default Project Structure
☀ Download Required Dependencies [Jars files]
☀ Compiles Source code
☀ Packaging projects as .jar, .war, .ear,....
☀ Starts Server
☀ Deploying Projects into Servers.
☀ Perform Unit Testing
☀ Preparing Test Reports.
☀ Preparing Documentations

☀ Undeploy applications from Servers 
☀ Stops Server.  

Project Object Model (pom)
☀ POM Stands for Project Object Model. 

☀ POM is the fundamental unit in Maven.
☀ POM is an XML file that contains information about the project and configuration details used by Maven to build the project.
☀ POM contains default values for projects like build directory, which is target; the source directory, which is src/main/java; the test source directory, which is src/test/java; and so on.
☀ In MAVEN 1, name of the pom file is "project.xml", in MAVEN2 it was renamed to pom.xml.
☀ When we execute MAVEN project then MAVEN will look for the project configurations in pom.xml file and gets the needed things and executes the project.  


     In Building MAVEN Projects, pom.xml file contains the following configurations.
1. Project Description
2. Repository
3. Dependency Management
4. Project Inheritance
5. Build Configuration
6. Build Profiles


1) Project Description
     In pom file, initial we will identify "Projection Description", it contains Project name, version number, packaged type, etc.
     To specify the above details, we need to use the following XML tags.
<project ..... >
   <!-- Project Description -->
   <modelVersion> --- </modelVersion>
   <groupid> --- </groupid>
   <artifactid> -- </artifactid>
   <version> -- </version>
    -----
    -----
</project>

☀ Where "<project>" tag is the root tag in pom.xml file
☀ Where "<modelVersion>" tag declared which version of the MAVEN we are using. <modelVersion> tag will take 4.0.0 to support for MAVEN2.x/3.x versions.
☀ Where "<groupid>" tag will take a unique ID for an organization, or a project. Normally we use a group ID similar to the root Java package name of the project.
☀ Where "<artifactid>" tag will take the name of the project. The artifact ID is used as name for a sub directory under the group ID directory in the Maven repository and as part of the name of the JAR file produced when building the project. The build result, a JAR, WAR or EAR file, is called an artifact in Maven.
☀ Where "<version>" tag will take the Project version number.
☀ Where "<packaging>" tag will take different packaging formats in order to deliver the project like jar, war, ear, etc.
<project ..... >
   <!-- Project Description -->
   <modelVersion>4.0.0</modelVersion>
   <groupid>com.ashok.banking</groupid>
   <artifactid>icici.accounts</artifactid>
   <version>1.0</version>
   <name>Account Application</name>
   <description> Application for Accounts module in ICICI Bank project </description>
   -----
</project>
2) Repository
     If we use Dependencies in MAVEN Project then MAVEN will search for the dependent JARs in Repositories. MAVEN will use three types of Repositories in order to get dependencies.
1. Local Repository
     It is a location to manage and supply all dependencies, it will be created by MAVEN when we execute any MAVEN command first time. In general, MAVEN will create Local Repository at "C:/Users/User_Name/.m2/repository"
E.g.
C:\Users\ashok.mariyala\.m2\repository

2. Central Repository
     It is a default Repository for MAVEN, it is located at "http://repo1.maven.org/maven2". In MAVEN applications, we will use some other repositories are also explicitly like.
1. http://repository.jboss.org/nexus/content/groups/public
2. http://mvnrepository.com
     In MAVEN applications, if we want to use the above explicit repositories then we have to configure them in pom file by using the following xml tags.
<repositories>
   <repository>
      <id>jboss</id> 
      <name>jboss repo</name>
      <url>http://repository.jboss.org/nexus/content/groups/public/</url>
   </repository>
</repositories>
3. Remote Repository
     In some Situations, Maven does not find the dependencies in Local Repository and in central repository, in this context, MAVEN stops the build process and generates some Exceptions. To overcome these problems, Maven has provided a new Features like "Remote Repository".
     Remote Repository is a developer's own custom repository containing required libraries or other project jars. To configure Remote Repository, we have to use the following XML tags in pom.xml file.
<repositories>
   <repository>
      <id>ashok.lib</id>
      <url>http://library.ashok.com/maven2/lib</url>
   </repository>
</repositories>
     When we run MAVEN project then MAVEN will search for the dependencies in the following order.
1. First, MAVEN will search for the dependencies in local repository, if the required dependencies are available at Local Repository the MAVEN will use them in application. If the dependencies are not available at Local Repository then MAVEN search for them at Central Repository.
2. If the required Dependencies are existed in central repository then MAVEN will load them into Local Repository and MAVEN will use them in the applications. If the required dependencies are not existed in Central Repository then MAVEN will search for them in Remote Repositories as per configuration.
3. If Remote Repository is not configured then MAVEN will stop the application execution and generated some Exceptions.
4. If Remote Repository is configured then MAVEN will search for the required dependencies in Remote Repository, if they are identified then MAVEN will load them into Local Repository for future reference. If the dependencies are not existed at Remote Repositories then MAVEN will stop the execution and generate some Exceptions.


3. Dependency Management 
     In Applications, Dependencies are the libraries [Collection of JARs] which are required to compile, test and run our applications. 
     In General, in application development, we will download the required libraries from the internet and we will store them in the application directory structure. 
     The main Advantage of MAVEN in applications development is that not to store any Dependent JAR files in Project Directory Structure by downloading them explicitly, MAVEN has given flexibility to the developers like to specify dependent JAR files names in pom file, where MAVEN will search for them in the repositories and MAVEN will load them into the project directory structure automatically. 
If we need any Library in MAVEN based applications then we have to declare them in pom file like below.
<dependencies>
   <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <version>3.5.6-Final</version>
      <scope>provided</scope>
   </dependency>
</dependencies>
     If we provide the dependency like above then MAVEN will search for the hibernate library with the name like
http://repo1.maven.org/maven2/org/hibernate/hibernate-core/3.5.6-Final/
     MAVEN is following "Transitive Dependencies Mechanism", that is, if our dependencies are required any other libraries then MAVEN will get them automatically without loading them explicitly by the developers.
Dependency Scopes
     In Applications, some dependencies are required to all phases of the project life cycle like compile, test, run,... and some other required only some of phases of the project life cycle. In order to limit the dependencies for the life cycle phases we will use Dependency Scopes.
There are 6 scopes available in MAVEN
1. Compile
2. Provided
3. Runtime
4. Test
5. System
6. Import

1. Compile
     It is the default scope in MAVEN . This scope will make the dependencies to avail all phases like compile, test, run, etc.
<dependencies>
   <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <version>3.5.6-Final</version>
      <scope>compile</scope>
   </dependency>
</dependencies>
Note: In general, hibernate-core library is required for all phases of the application.

2. Provided
     This scope will make the dependency libraries to avail up to compilation and and up to testing, not for run time, because, at run time, JDKs or Containers will provide the required dependencies at run time.
     In web applications, Servlet API is required explicltly to compile and test the project, but, Servlet API is provided by the container at run time automatically, so that, they are not required to be exported at run time.
<dependencies>
   <dependency>
      <groupId>javax.servlet</groupId>
      <artifactId>servlet-api</artifactId>
      <version>3.0.1</version>
      <scope>provided</scope>
   </dependency>
</dependencies>
3. Runtime
     This scope indicates that the dependency is not required for compilation, but is for execution. It is in the run time and test class paths, but not the compile class path.
<dependencies>
   <dependency>
      <groupId>com.thoughtworks.xstream</groupId>
      <artifactId>xstream</artifactId>
      <version>1.4.4</version>
      <scope>runtime</scope>
   </dependency>
</dependencies>
4. Test
     This scope indicates that the dependency is not required for normal use of the application, and is only available for the test compilation and execution phases. This scope is not transitive.
<dependencies>
   <dependency>
      <groupId>junit</groupId>
      <artifactId>junit</artifactId>
      <version>4.12</version>
      <scope>test</scope>
   </dependency>
</dependencies>
5. System
     Dependencies with system are similar to ones with scope provided. The only difference is system dependencies are not retrieved from remote repository. They are present under project’s sub directory and are referred from there.
<dependencies>
   <dependency>
      <groupId>Explicit_Dependency</groupId>
      <artifactId>Explicit_Dependency</artifactId>
      <version>4.12</version>
      <scope>system</scope>
      <systemPath>apps\app.war\WEB-INF\lib\Explicit_Dependency.jar</systemPath>
   </dependency>
</dependencies>
6. Import
     It is available in Maven 2.0.9 or later. Import scope is only supported on a dependency of type pom in the dependencyManagement section. It indicates the dependency to be replaced with the effective list of dependencies in the specified POM’s dependencyManagement section.
<dependencyManagement>
   <dependencies>
      <dependency>
         <groupId>other.pom.group.id</groupId>
         <artifactId>other-pom-artifact-id</artifactId>
         <version>SNAPSHOT</version>
         <scope>import</scope>
         <type>pom</type>
      </dependency>
   </dependencies>
</dependencyManagement>
4. Project Inheritance
     In MAVEN based applications, it is possible to inherit configurations from one pom file to another pom file inorder to avoid configurations redundency. To declare parent pom , we have to use "pom" as value to <packaging> tag in parent pom file.
<project ..... >
   <!-- Project Description -->
   <modelVersion>4.0.0</modelVersion>
   <groupid>com.ashok.banking</groupid>
   <artifactid>icici.accounts</artifactid>
   <version>1.0</version>
   <name>Account Application</name>
   <packaging>pom</packaging>
   -----
</project>
     If we want to inherit parent pom configuration details into a particular child pom then we have to configure parent pom in child pom.
<project ..... >
   <parent>
      <groupid>com.ashok.banking</groupid>
      <artifactid>icici.accounts</artifactid>
      <version>1.0</version>
   </parent>
   -----
</project>
Note: In JAVA, java.lang.Object class is common and default super class for every java class in order to provide 11 common and default methods to each and every java class, similarly , there is a common and default super pom file is existed in maven in order to provide all common configurations and settings to the child pom file. In general, parent pom contains the following configurations
1. Common data – Developers’ names, SCM address, distribution management etc.
2. Constants – Such as version numbers
3. Common dependencies – Common to all child. It has same effect as writing them several times in individual pom files.
4. Properties – For example plugins, declarations, executions and IDs.
5. Configurations
6. Resources
Note: By default, Maven looks for the parent POM first at project’s root, then the local repository, and lastly in the remote repository. If parent POM file is not located in any other place, then you can use code tag. This relative path shall be relative to project root.
<parent>
   <groupid>com.ashok.banking</groupid>
   <artifactid>icici.accounts</artifactid>
   <version>1.0</version>
   <relativePath>../baseapp/pom.xml</relativePath>
</parent>
Note:
☀ If we want to get super pom from MAVEN then use the following command on command prompt from the project root location which contains project specific pom file.
mvn help:effective-pom
☀ Where effective-pom is super pom configurations and project configurations.

5. Build Configuration
   In MAVEN , Build Configuration is mainly for plugin configurations, resources configurations,.....which are required in MAVEN Project.
     MAVEN is simply the collection of plugins, where plugins are used to perform the actions like creating jar files, creating war files, compile Source code, executing unit test code, create project documentation, etc.
     MAVEN is having "Plugin Execution Framework" at its heart in order to execute all plugins. In MAVEN , there are two types of Plugins.
1. Build Plugins
2. Reporting Plugins

1. Build Plugins: These plugins are executed during the build and they should be configured in the <build/> element from the POM.
1. Clean : It is used when you want to remove files generated at build-time in a project's directory.
2. Compiler: Compiles Java source code.
3. Deploy: It can be used to store artifacts in remote repository while deploying the applications in order to share to other projects .
4. Install: It can be used to install artifacts into local repository.
5. Resources: It will include all the project resources in output directory while creating aJAR files.
6. Ear: create ear file from the current project.
7. jar: creates jar file from the current project.
8. war: creates war file from the current project.
9. rar: creates rar file from the current project.

2. Reporting plugins: These plugins are executed during the site generation and they should be configured in the <reporting/> element from the POM.
1. changelog: Generate a list of recent changes from your SCM[Software Configuration Management].
2. changes: Generate a report from an issue tracker or a change document.
3. javadoc: Generate Javadoc for the project.
4. project-info-resports: Generate standard project reports.
5. surfire-report: Generate a report based on the results of unit tests.
     In general, we will use MAVEN compiler plugin inorder to perform Compilation, for this we have to use the following xml tags in pom.xml file.
<project ---- >
   <build>
      <plugins>
         <plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-compiler-plugin</artifactId>
              <configuration>
                 <source>1.8</source>
                 <target>1.8</target>
              </configuration>
         </plugin>
      </plugins>
   </build>
</project>
     By default, all files placed in "src\main\config" are packaged into the generated project artifact and any file which we placed in "src\test\resources" are available in project class path during unit tests.
     If we want to provide our own customized resources location in project then we have to configure them in pom.xml file under <build> tag like below.
<build>
   ......
   <resources>
      <resource>
        <directory>src/main/config</directory</directory>
      </resource>
      <resource>
         <directory>src/main/resources</directory</directory>
      </resource>
   </resources>
   ...
</build>
6. Build Profiles
     In general, profiles are used to customize the build life cycle for different environments like development, testing, production, etc.
<profiles>
   <profile>
      <id>development</id>
      <activation>
         <activeByDefault>true</activeByDefault>
      </activation>
      <properties>
         <jdbc.connection.url>jdbc:oracle:thin:@localhost:1521:xe</jdbc.connection.url>
      </properties>
   </profile>
   <profile>
      <id>test</id>
      <properties>
         <jdbc.connection.url>jdbc:mysql://localhost:3306/ashokdb</jdbc.connection.url>
      </properties>
   </profile>
</profiles>
     Where each and every profile has its own id, it can be used to access the respective environment or profile.
In src/main/resources/db.properties
jdbc.connection.url = ${jdbc.connection.url}
     If we provide the above setups like above then at compilation time, the respective jdbc URL will be injected to the "jdbc.connection.url" property depending on the target environment. Use the following command on command prompt inorder to compile the project.
mvn compile
    Here "jdbc.connection.profile" property will take "jdbc:oracle:thin:@localhost: 1521:xe" value.
mvn compile -Ptest
     Here "jdbc.connection.profile" property will take "jdbc:mysql://localhost:3306/ashokdb" value. jdbc.connection.url = ${jdbc.connection.url}
     If we provide the above setups like above then at compilation time, the respective jdbc URL will be injected to the "jdbc.connection.url" property depending on the target environment.

No comments:

Post a Comment