Monday, March 24, 2014

Maven Overview

What is Maven? From the website, the answer to the question:
Maven is an attempt to apply patterns to a project's build infrastructure in order to promote comprehension and productivity by providing a clear path in the use of best practices. Maven is essentially a project management and comprehension tool and as such provides a way to help with managing:
  • Builds
  • Documentation
  • Reporting
  • Dependencies
  • SCMs
  • Releases
  • Distribution
Maven is not just a build tool, and not just a replacement for Ant. Maven is an entirely different creature from Ant. Ant is simply a toolbox whereas Maven is about the application of patterns in order to achieve an infrastructure which displays the characteristics of:
  • Coherence - Maven allows organizations to standardize on a set of best practices. Because Maven projects adhere to a standard model they are less opaque. The definition of this term from the American Heritage dictionary captures the meaning perfectly: "Marked by an orderly, logical, and aesthetically consistent relation of parts."
  • Reusability - Maven is built upon a foundation of reuse. When you adopt Maven you are effectively reusing the best practices of an entire industry.
  • Agility - Maven lowers the barrier to reuse not only of build logic but of components. When using Maven it is easier to create a component and integrate it into a multi-project build. It is easier for developers to jump between different projects without a steep learning curve that accompanies a custom, home-grown build system.
  • Maintainability - Organizations that adopt Maven can stop building the build, and start focusing on the application. Maven projects are more maintainable because they have fewer surprises and follow a common model.
To get an ant project up and running, you usually need to cut and paste a build script and get started laying out your environment. Maven allows you to skip this step and install a new project.
Quick Start
Once maven is installed and on the classpath, all one has to do, from project root execute:
mvn archetype:create -DgroupId=com.mycompany.app -DartifactId=my-app
This results in the directory structure:
my-app
|-- pom.xml
`-- src
    |-- main
    |   `-- java
    |       `-- com
    |           `-- mycompany
    |               `-- app
    |                   `-- App.java
    `-- test
        `-- java
            `-- com
                `-- mycompany
                    `-- app
                        `-- AppTest.java
The starting pom.xml file looks like:
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://maven.apache.org/POM/4.0.0" 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>my-app</artifactid>

  <packaging>jar</packaging>

  <version>1.0-SNAPSHOT</version>

  <name>Maven Quick Start Archetype</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>
The following are the most common "targets"
  • compile - compile the code
  • test - compile and run the test cases
  • test-compile - compile the test classes
  • package - build the jar
  • install - install the package into a repository

Repository
Maven supports the concept of repositories. These can be local or remote libraries of all the necessary jar files. Each project defines dependencies (see dependencies element in the pom.xml above).

In the default setting, the expected jar file will be located in ~user/.m2/repository. The behavior can be changed in settings.xml of the maven installation. 

A jar file can have its own pom file declared which will create nested dependency chains. So if your project requires soap, and soap requires the activation, and mail jars, these dependencies can be within the soap pom.

Local repo:
\~user/.m2/repository/[groupid]/[artifactid]/[version]/[artificatid]-[version]
In the case of the above example, the location of the jar file:
\~/.m2/repository/junit/junit/3.8.1/junit-3.8.1.jar

Remote repo:
What happens if the jars are not there. By default Maven will go out and attempt to download them. One of the most popular remote repositories is ibiblio.com, which is the apache jar library. Of course, you can specify other repositories. Furthermore, you can prevent maven from using a particular location.

Plugins
Plugins are very similar to dependencies. Its just a project action dependency.  Using plugins allows the user to customize the build for their project. In the following example, I demonstrate the jaxb plugin for generating source files from an xsd.


<plugins>

    <plugin>

        <groupId>com.sun.tools.xjc.maven2</groupId>

    <artifactId>maven-jaxb-plugin</artifactId>

    <executions>

        <!?Which phase the plugin should be executed in -->

        <execution>

            <goals>

            <goal>generate</goal>

        </goals>

        </execution>

    </executions>

    <configuration>

    <!?The package name -->

            <generatePackage>com.riskfocus.markit.generated</generatePackage>

            <!- - Which schema files to include -->

            <includeSchemas>

        <includeSchema>**/*.xsd</includeSchema>

            </includeSchemas>

            <includeBindings>

        <includeBinding>*.xjb</includeBinding>

        </includeBindings>

        <!?Where should the generated files be placed -->

        <generateDirectory>src/main/java</generateDirectory>

        </configuration>

    </plugin>

</plugins>


It takes a little bit of hunting the first time around to understand how to structure the plug in declaration. However, most times, someone out there has already done it.

Ant
A further benefit, there is an ant task supported. So if you cant do it the maven way, you can always plug in an ant task.
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-antrun-plugin</artifactId>
    <executions>
        <execution>
            <id>apt-task</id>
            <phase>generate-sources</phase>
            <configuration>
                <tasks verbose="true">
            <property name="gen.src.java" value="target/generated-sources/main/java"/>
            <mkdir dir="${gen.src.java}"/>
                <taskdef name="apt" classname="com.sun.tools.ws.ant.Apt">
                    <classpath refid="maven.compile.classpath"/>
                </taskdef>
                <apt fork="true" debug="false" verbose="false" destdir="target/classes" sourcedestdir="${gen.src.java}"
                                     nocompile="true" sourcepath="src/main/java">
                    <classpath>
                    <path refid="maven.compile.classpath"/>
                    <pathelement location="${java.home}/../lib/tools.jar"/>
                </classpath>
                <option key="r" value="target"/>
                <source dir="src/main/java">
                    <include name="**/websvcs/**/*.java"/>
                </source>
                </apt>
            </tasks>
            <sourceRoot>${gen.src.java}</sourceRoot>
            </configuration>
            <goals>
            <goal>run</goal>
     </goals>
     </execution>
</executions>

This task attempts to generate a wsdl file from an annotated java class.   
Should ant be an absolute requirement, I believe that you can generate an ant build.xml for your pom.
How does maven determine the classpath resources for your project. The first is the dependency tag, which indicates the jar or project dependency. Yes, you can declare multiple projects with their own hierarchies within your project pom.

Resources reside, by default, in src/main/resources. Any resource file added here will automatically be picked up. For test cases, the pattern is to add src/test/resources.

Maven supports project scaffolding, i.e. template generation, for different project types, so calledarchtype. The goal of this scaffolding is to allow a fast start into the Maven world and supports a "standardized" folder structure of software projects.
You can create a project by executing the generate goal on the archetype plugin : $mvn archetype:generate . This starts the generate process in the interactive mode and asks you for several settings. Artifact properties
Name
Description
groupId
defines a unique base name of the organization or group that created the project. This is normally a domain name. For the generation the groupId also defines the package of the main class.
artifactId
defines the unique name of the artifact. In our case it's the same like the groupId, but it could also be a simple name like "SuperCalculator". The generation uses this value as name of the root folder for out project.
packaging
defines the packaging method. This could be e.g. jar, war or ear. This setting has influence on the whole life cycle.
version
This defines the version of the artifacts generated from our project.
url
defines the project site.
The configuration of a Maven project is done via a Project Object Model, which is represented by thepom.xml file.
By default, this is the only configuration file required for the build process. Every build follows a specified life cycle. Maven comes with a default life cycle that includes the most common build phaseslike compiling, testing and packaging. All phases are made up of plugin goalsPlugin goals are tasks which are more specific than phases. So a phase can be defined to run more than one plugin goal.
The result of a build is called artifact. An artifact, for example, can be a executable or an archive of documents.
With this single line, the maven lifecycle will be started. So the configuration from the pom.xml will be loaded and the dependencies will be resolved. After this, Maven tries to load the lastest version of the depended artifacts from the central repository into a local repository, which is placed as.m2/repository in the users home directory. As part of the lifecycle, the build tool compiles the sources and tests, runs the tests and packs the compiled files in, e.g., JAR archives. As last step the resulting artifact will be saved in the local repository, so it can be used by other projects.
Maven creates the build result in the target folder. If you run the mvn install command, Maven compiles the source code, builds the result, e.g., the JAR file.
# default to run Maven
# compiles, build and install the build result
maven install 
By default, Maven checks online if the dependencies have been changed. If you want to use your local repository, you can use the -o to tell Maven to work offline.
# work offline , i.e. use the local maven repository
maven -o clean install 
C:\Java\maven >mvn archetype:generate -DgroupId=mavenexample -DartifactId=mavenexample -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
CD mavenexample
C:\Java\maven\mavenexample >mvn archetype:generate -DgroupId=mavenexample -DartifactId=mavenexample -DarchetypeArtifactId=maven-archetype-quickstart -DinteractiveMode=false
C:\Java\maven\mavenexample>java -cp target/mavenexample-1.0-SNAPSHOT.jar mavenexample.App
To run specific phases:
$ mvn package
$ mvn test
$ mvn compile
$ mvn clean 

No comments:

Popular micro services patterns

Here are some popular Microservice design patterns that a programmer should know: Service Registry  pattern provides a  central location  fo...