Maven small note 1 & 2

266 阅读11分钟

START WITH MAVEN

Apache Maven is an open source, standards-based project management framework that simplifies the building, testing, reporting, and packaging of projects. Maven's initial roots were in the Apache Jakarta Alexandria project that took place in early 2000. It was subsequently used in the Apache Turbine project. Like many other Apache projects at that time, the Turbine project had several subprojects, each with its own Ant-based build system. Back then, there was a strong desire for developing a standard way to build projects and to share generated artifacts easily across projects. This desire gave birth to Maven. Maven version 1.0 was released in 2004, followed by version 2.0 in 2005 and version 3.0 in 2010.

Standardized Directory Structure

Often, when we start work on a new project, a considerable amount of time is spent deciding on the project layout and folder structure needed to store code and configuration files. These decisions can vary vastly across projects and teams, which can make it difficult for new developers to understand and adopt other teams' projects. It can also make it hard for existing developers to jump between projects and find what they are seeking.

Maven addresses the preceding problems by standardizing the folder structure and organization of a project. Maven provides recommendations on where different parts of a project, such as source code, test code, and configuration files, should reside. For example, Maven suggests that all of the Java source code should be placed in the src\main\java folder. This makes it easier to understand and navigate any Maven project.

Additionally, these conventions make it easy to switch to and start using a new IDE. Historically, IDEs varied with project structure and folder names. A dynamic web project in Eclipse might use the WebContent folder to store web assets, whereas IntelliJ IDEA might use web folder for the same purpose. With Maven, your projects follow a consistent structure and become IDE agnostic.

Declarative Dependency Management

Most Java projects rely on other projects and open source frameworks to function properly. It can be cumbersome to download these dependencies manually and keep track of their versions as you use them in your project.

Maven provides a convenient way to declare these project dependencies in a separate, external pom.xml file. It then automatically downloads those dependencies and allows you to use them in your project. This simplifies project dependency management greatly. It is important to note that in the pom.xml file, you specify the what and not the how. The pom.xml file can also serve as a documentation tool, conveying your project dependencies and their versions.

Plug-ins

Maven follows a plug-in-based architecture, making it easy to augment and customize its functionality. These plug-ins encapsulate reusable build and task logic. Today, there are hundreds of Maven plug-ins available that can be used to carry out tasks ranging from code compilation to packaging to project documentation generation.

Maven also makes it easy to create your own plug-ins, thereby enabling you to integrate tasks and workflows that are specific to your organization.

Uniform Build Abstraction

Maven provides a uniform interface for building projects. You can build a Maven project by using just a handful of commands. Once you become familiar with Maven's build process, you can easily figure out how to build other Maven projects. This frees developers from having to learn build idiosyncrasies so they can focus more on development.

Tools Support

Maven provides a powerful command-line interface to carry out different operations. All major IDEs today provide excellent tool support for Maven. Additionally, Maven is fully integrated with today's continuous integration products such as Jenkins and Bamboo.

Archetypes

As we already mentioned, Maven provides a standard directory layout for its projects. When the time comes to create a new Maven project, you need to build each directory manually, and this can easily become tedious. This is where Maven archetypes come to rescue. Maven archetypes are predefined project templates that can be used to generate new projects. Projects created using archetypes will contain all of the folders and files needed to get you going.

Archetypes are also a valuable tool for bundling best practices and common assets that you will need in each of your projects. Consider a team that works heavily on Spring framework-based web applications. All Spring-based web projects share common dependencies and require a set of configuration files. It is also highly possible that all of these web projects have similar Log4j/Logback configuration files, CSS/Images, and Thymeleaf page layouts. Maven lets this team bundle these common assets into an archetype. When new projects get created using this archetype, they will automatically have the common assets included. No more copy and pastes of code or drag and drops of files required.

Open Source

Maven is open source and costs nothing to download and use. It comes with rich online documentation and the support of an active community.

Convention Over Configuration

Convention over configuration (CoC) or coding by convention is one of the key tenants of Maven. Popularized by the Ruby on Rails community, CoC emphasizes sensible defaults, thereby reducing the number of decisions to be made. It saves time and also results in a simpler end product, as the amount of configuration required is drastically reduced.

As part of its CoC adherence, Maven provides several sensible defaults for its projects. It lays out a standard directory structure and provides defaults for the generated artifacts. Imagine looking at a Maven artifact with the name log4j-core-2.11.2.jar. At a glance, you can easily see that you are looking at a log4j-core JAR file, version 2.11.2.

One drawback of Maven's CoC is the rigidness that end users experience when using it. To address this, you can customize most of Maven's defaults. For example, it is possible to change the location of the Java source code in your project. As a rule of thumb, however, such changes to defaults should be minimized.

Maven Alternatives

ANT + IVY

Apache Ant ( ant.apache.org ) is a popular open source tool for scripting builds. Ant is Java based, and it uses Extensible Markup Language (XML) for its configuration. The default configuration file for Ant is the build.xml file.

Using Ant typically involves defining tasks and targets. As the name suggests, an Ant task is a unit of work that needs to be completed. Typical tasks involve creating a directory, running a test, compiling source code, building a web application archive (WAR) file, and so forth. A target is simply a set of tasks. It is possible for a target to depend on other targets. This dependency lets us sequence target execution. Listing demonstrates a simple build.xml file with one target called compile . The compile target has two echo tasks and one javac task.

<project name="Sample Build File" default="compile" basedir=".">

<target name="compile" description="Compile Source Code">

<echo message="Starting Code Compilation"/>

<javac srcdir="src" destdir="dist"/>

<echo message="Completed Code Compilation"/>

</target>

</project>

Ant doesn't impose any conventions or restrictions on your project, and it is known to be extremely flexible. This flexibility has sometimes resulted in complex, hard-to-understand, and hard-to-maintain build.xml files.

Apache Ivy ( ant.apache.org/ivy/ ) provides automated dependency management, making Ant more joyful to use. With Ivy, you declare the dependencies in an XML file called ivy.xml, as shown in Listing. Integrating Ivy with Ant involves declaring new targets in the build.xml file to retrieve and resolve dependencies.

<ivy-module version="2.0">

<info organisation="com.apress" module="gswm-ivy" />

<dependencies>

<dependency org="org.apache.logging.log4j" name="log4j-api" rev="2.11.2" />

</dependencies>

</ivy-module>

GRADLE

Gradle ( gradle.org/ ) is an open source build, project automation tool that can be used for Java and non-Java projects. Unlike Ant and Maven, which use XML for configuration, Gradle uses a Groovy-based domain-specific language (DSL).

Gradle provides the flexibility of Ant, and it uses the same notion of tasks. Listing shows a default build.gradle file.

plugins {
    id 'java'
}

version = '1.0.0'

repositories {
    mavenCentral()
}

dependencies {
    testCompileOnly group: 'junit', name: 'junit', version: '4.10'
}

Gradle's DSL and its adherence to CoC results in compact build files. The first line in Listing includes a Java plug-in for build's use. Plug-ins in Gradle provide preconfigured tasks and dependencies to the project. The Java plug-in, for example, provides tasks for building source files, running unit tests, and installing artifacts. The dependencies section in the default.build file instructs Gradle to use JUnit dependency during the compilation of test source files. Gradle's flexibility and performance have contributed to its growing popularity. However, the learning curve for Gradle and Groovy DSL could be steep. IDE and plug-in support for Gradle is also less mature when compared to Maven.

Despite growing competition from other tools, Maven continues to dominate the build tool space. This is evident in Figure. Which shows the results of a 2018 survey by Synk.io ( snyk.io/blog/jvm-ec… ) on the build tools used by Java developers.

image.png

The Polyglot for Maven Project ( github.com/takari/poly… ) allows you to create Maven's POM files in dialects other than XML. Supported languages include Groovy, Ruby, Scala, YAML, and Java.

Maven Components

Maven relies on several components to get its job done. Though you might not interact with these components directly, an overview of these components helps understand the internal workings of Maven and better equip you to troubleshoot Maven errors.

MAVEN SCM

Maven interacts with several source control/code management (SCM) systems to perform operations such as checking out code or creating a branch or a tag. The Maven SCM ( maven.apache.org/scm/ ) project provides a common API to perform such operations. The Maven release plug-in discussed in Chapter8 heavily relies on Maven SCM components. Maven SCM currently supports several popular code management systems such as Git, Subversion, and Perforce.

MAVEN WAGON

As discussed earlier, Maven automatically downloads project dependencies such as JAR files from different locations such as FTPs, file systems, and web sites. The Maven Wagon ( maven.apache.org/wagon/ ) project provides a transport abstraction that enables Maven to interact with different transport protocols easily and retrieve dependencies. Maven Wagon supports some of the popular protocols such as

  • File: Allows retrieval of dependencies using file system protocol.

  • HTTP: Allows retrieval of dependencies using HTTP/HTTPS protocols. Two implementation variations are provided – one that uses Apache HttpClient and the other that uses standard Java library.

  • FTP: Allows retrieval of dependencies using File Transfer Protocol.

MAVEN DOXIA

Maven Doxia ( maven.apache.org/doxia/ ) is a content generation framework that can be used to generate static/dynamic content such as PDF files and web pages. Doxia supports several popular markup languages such as Markdown, Apt, XHTML, and Confluence. Maven relies heavily on Doxia to generate project documentation and reports (more on this in Chapter 7.

Summary

Apache Maven greatly simplifies the build process and automates project management tasks. This chapter provided a gentle introduction to Maven and described the main reasons for adopting it. We also looked at Maven's close peers: Ant + Ivy and Gradle.

In the next chapter, you will learn about the setup required to get up and running with Maven.

2. Setting Up Maven

Maven installation is an easy and straightforward process. This chapter will explain how to install and set up Maven using the Windows 10 and Mac operating systems. You can follow similar procedure with other operating systems.

Note Maven is a Java-based application and requires the Java Development Kit (JDK) to function properly. Maven version 3.6 requires JDK 1.7 or above. Before proceeding with Maven installation, make sure that you have Java installed. If not, install the JDK (not just Java Runtime Environment [JRE]) from www.oracle.com/technetwork… . Ensure that you have the JAVA_HOME environment variable set and pointing to the JDK installation. In this book, we will be using JDK 8.

You will begin the installation process by downloading the latest version of Maven from the Apache Maven web site ( maven.apache.org/download.ht… ). At the time of this writing, the latest version is 3.6.1. Download the Maven 3.6.1 binary .zip file as shown in Figure

A332298_2_En_2_Fig1_HTML.jpg

Figure 2-1

Maven archive download

Once the download is complete, unzip the distribution to a local directory on your computer. It will create a folder named apache-maven-3.6.1-bin and the contents of the folder are shown in Figure.

A332298_2_En_2_Fig2_HTML.jpg

Figure 2-2

Maven install directory contents

The bin folder contains platform-specific Maven executables – mvn.cmd file for Windows and mvn.sh for Mac and Unix/Linux platforms that you can use to launch Maven. The debug versions of these executables – mvnDebug.cmd and mvnDebug.sh – include debugging arguments that allow you to attach an IDE to a running Maven process for remote debugging.

That boot folder contains the “plexus-classworlds-2.5.2.jar” file. Maven uses Plexus Classworlds framework (codehaus-plexus.github.io/plexus-clas…) to build its classloader graph.

The conf folder contains configuration files that you can use to alter Maven’s default behaviors. An important file in this folder is the settings.xml file which we will cover later in the chapter. Another file is the simplelogger.properties file that allows you to control Maven's logging. For example, the log level can be changed to debug by setting the defaultLogLevel property to debug. Similarly, you can change the logFile property to write log output from “System.out” to a file.

Finally, the lib folder contains the libraries that are essential for Maven and its plug-ins to run properly.

Installing on Windows

Move the contents of the apache-maven-3.6.0-bin to a new directory c:\tools\maven. The next step is to add the Maven executable to the PATH Environment variable so that you can run Maven commands from the command line. In Windows Search box, search for “Environment Variable” and select “Edit the system environment variables”. In the resulting window, click the Environment Variables button, and select the PATH variable and click Edit. Click New and enter the value “C:/tools/maven/bin” and click OK.

Installing on Mac

Move the contents of the apache-maven-3.6.0-bin folder into HOME/tools/mavenwhereHOME/tools/maven where HOME is your home directory on Mac. Edit .bash_profile file by running the command nano ~/.bash_profile. Add Maven executable to the PATH variable by adding the following line to .bash_profile:

export PATH=$HOME/tools/maven/bin:$PATH

This completes the Maven installation. If you have any open command-line windows/terminals, close them and reopen a new command-line window. When environment variables are added or modified, new values are not propagated to open command-line windows automatically.

Maven_Opts Environment Variable

When using Maven, especially in a complex project, chances are that you will run into OutOfMemory errors. This may happen, for example, when you are running a large number of JUnit tests or when you are generating a large number of reports. To address this error, increase the heap size of the Java virtual machine (JVM) used by Maven. This is done globally by creating a new environment variable called MAVEN_OPTS. To begin, we recommend using the value -Xmx512m.

Testing Installation

Now that Maven is installed, it’s time to test and verify the installation. Open a Command Prompt and run the following command:

mvn –v

On a Windows machine, this command should output information similar to the following:

C:\> mvn –v

Apache Maven 3.6.1 (d66c9c0b3152b2e69ee9bac180bb8fcc8e6af555; 2019-04-04T13:00:29-06:00)

Maven home: C:\tools\maven\bin\..

Java version: 1.8.0_144, vendor: Oracle Corporation, runtime: C:\Java\jdk1.8.0_144\jre

Default locale: en_US, platform encoding: Cp1252

OS name: "windows 10", version: "10.0", arch: "amd64", family: "windows"

The –v command-line option tells the path where Maven is installed and what Java version it is using. You would also get the same results by running the expanded command mvn --version.

Getting Help

You can get a list of Maven’s command-line options by using the -h or --help options. Running the following command will produce output similar to that shown in figure

A332298_2_En_2_Fig3_HTML.jpg

Figure 2-3

Results of running Maven Help command

Additional Settings

The installation steps we have provided so far are enough to get you started with Maven. However, for most enterprise uses, you need to provide additional configuration information. This user-specific configuration is provided in a settings.xml file. Maven looks for the settings.xml file in two locations – in the conf folder of Maven’s installation and .m2 folder in the user’s home directory. The settings.xml file under conf folder is called global settings, and the file under .m2 folder is referred to as user settings. If both files exist, Maven will merge the contents of two files and the user settings will take precedence.

Note

The .m2 folder is important to Maven’s smooth operation. Among many things, this folder houses a settings.xml file and a repository folder. The repository folder contains plug-in JAR files and metadata that Maven requires. It also contains the project-dependent JAR files that Maven downloaded from the Internet. We will take a closer look at this folder in Chapter 3.

By default, the .m2 folder is located in your home directory. In Windows, this directory is usually c:\Users\<<your_user_name>>. On Mac, this directory is usually /Users/<<your_user_name>>/.m2/repository. You can run the command mvn help:evaluate -Dexpression=settings.localRepository to identify the local repository location.

When you run a Maven command, Maven automatically creates the .m2 folder. If you don’t see this folder on your computer, however, go ahead and create one.

Out of the box, the .m2 folder does not contain a settings.xml file. In the .m2 folder on your local computer, create a settings.xml file and copy the contents of the skeleton settings.xml file as shown in Listing. We will cover some of these elements in the coming chapters. A brief description of some of the elements is provided in Table

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0

    http://maven.apache.org/xsd/settings-1.0.0.xsd">

    <localRepository/>

    <interactiveMode/>

    <offline/>

    <pluginGroups/>

    <servers/>

    <mirrors/>

    <proxies/>

    <profiles/>

    <activeProfiles/>

</settings>

Listing 2-1 Skeleton Settings.xml Contents

Element NameDescription
localRepositoryMaven stores copies of plug-ins and dependencies locally in the c:\Users\<<your_user_name>>\.m2\repository folder. The localRepository element can be used to change the path of the local repository. For example, <localRepository>c:\mavenrepo</localRepository> will change the repository location to the mavenrepo folder.
interactiveModeAs the name suggests, when this value is set to true, Maven interacts with the user for input. If the value is false, Maven will try to use sensible defaults. The default is true.
offlineWhen set to true, this configuration instructs Maven to not connect to network and operate in an offline mode. With offline mode set to true, Maven will not attempt to download new dependencies or updates to dependencies. The default is false.
serversMaven can interact with a variety of servers, such as Git servers, build servers, and remote repository servers. This element allows you to specify security credentials, such as the username and password, which you need to connect to those servers.
mirrorsAs the name suggests, mirrors allow you to specify alternate locations for downloading dependencies from remote repositories. For example, your organization might have mirrored a public repository on their internal network. The mirror element allows you to force Maven use the internal mirrored repository instead of the public repository.
proxiesProxies contain the HTTP proxy information needed to connect to the Internet.

Table 2-1 Details of the settings.xml Elements

Setting Up a Proxy

As we will discuss in detail in Chapter 3, Maven requires an Internet connection to download plug-ins and dependencies. Some companies employ HTTP proxies to restrict access to the Internet. In those scenarios, running Maven will result in Unable to download artifact errors. To address this, edit the settings.xml file and add the proxy information specific to your company. A sample configuration is shown in Listing 2-2

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"

    xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

    xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0

    http://maven.apache.org/xsd/settings-1.0.0.xsd">

    <proxies>

        <proxy>

            <id>companyProxy</id>

            <active>true</active>

            <protocol>http</protocol>

            <host>proxy.company.com</host>

            <port>8080</port>

            <username>proxyusername</username>

            <password>proxypassword</password>

            <nonProxyHosts />

        </proxy>

    </proxies>

</settings>

Listing 2-2 Settings.xml with Proxy Content

SECURING PASSWORDS

The password to connect to the proxy server in section 2-2 is stored in clear text in the settings.xml file. If you were to accidentally share your settings.xml file, your password will be compromised. To address this, Maven provides a mechanism to encrypt the passwords that get stored in settings.xml file.

We begin the encryption process by creating a master password using the following code:

mvn -emp mymasterpassword

{LCWw0+NAqw0HuYH9HNz+1D7aElXM242PtuyoDXDAuelxjwZC8MyXaACkHSy7tZwU}

Maven requires the newly generated master password to be saved in a settings-security.xml file under .m2 folder. Create a new settings-security.xml file under .m2 folder and copy the following contents into that file.

<settingsSecurity>

<master>{LCWw0+NAqw0HuYH9HNz+1D7aElXM242PtuyoDXDAuelxjwZC8MyXaACkHSy7tZwU}</master>

</settingsSecurity>

Run the following command to encrypt the “proxypassword” password. Once the command completes, copy the output and replace the clear text password in settings.xml file with it:

mvn -ep proxypassword

{i4RnaIHgxqgHyKYySxor+cvshmHweTAvNjuORNYyu5w=}

Though the preceding process encrypts the passwords and avoids the need to save passwords in clear text, it is important to remember that anyone that has access to settings-security.xml file can easily decode the master password and subsequently decrypt the passwords in the settings.xml file. One mechanism to address this is to store the settings-security.xml file in an external device such as USB drive.