Image of a plain as a blank canvas for our custom software development

Maven Tutorial

Arteco - Information Technologies
  • :)
  • :0
  • :D
  • ;)
  • :]
foto Ramón Arnau

Ramón Arnau

Gerente de Arteco Consulting SL

Understand how MAVEN works and learn to get the most out of the most used Java Project Construction Software

Maven is the tool par excellence for controlling the construction and downloading dependencies of any Java application. From compilation to building the final binary, including unit tests. In the following lines, we will show you what you need to know to become a Maven professional.

What is Maven

Maven is an Open Source tool developed in Java by the Apache Foundation association, a non-profit organization that publishes copyright-free resources to ensure development and innovation in information technology. The goal of this tool is to facilitate and standardize the organization and construction of software projects, mainly for projects intended for the Java Virtual Machine.

How to Install Maven

Below, we explain the detailed process to properly configure it on your development station.

How to Install Maven on Ubuntu

Just as with the installation of the JDK, the Maven build and dependency management tool for Java projects will be installed in a similar way:

sudo apt install maven

Resulting in the installation of the mvn command that we can run from any directory. To verify the installation, we can check the version by running:

mvn -version

If there were no issues during the installation, you should see output similar to the following:

Apache Maven 3.6.0
Maven home: /usr/share/maven
Java version: 11.0.6, vendor: Ubuntu, runtime: /usr/lib/jvm/java-11-openjdk-amd64
Default locale: es_ES, platform encoding: UTF-8
OS name: "linux", version: "5.3.0-42-generic", arch: "amd64", family: "unix"

Lastly, we just need to install the Java programming editor that interests us the most.

Download Apache Maven for Win/Mac

Since Maven is programmed in Java, it is portable, meaning the same distribution can be used on any platform that can run the JVM. Simply go to the official Maven project page and download the latest stable version. It is offered in several formats, and the Zip extension will be sufficient in most cases.

Once downloaded, refer to the section for your platform to see how to configure it correctly.

Configure Apache Maven for Windows

Configuring Maven for Windows is very simple. Just unzip the downloaded Zip file from the previous step and place the files in a directory. For example, in the directory where the JDK files are stored: c:\Program Files\Java\apache-maven-version. Note the full path because it will be needed in the next step.

Once the files are unzipped, you will need to create the MAVEN_HOME environment variable pointing to the aforementioned path, the base of the installation. Using this variable allows you to switch from one Maven distribution to a more updated version without changing all the references scattered throughout the projects.

Lastly, add the Java binaries path to the Path environment variable so that we can invoke Maven with the mvn command from any directory:

Path=%MAVEN_HOME%\bin;%Path%

If the configuration is done correctly, we can invoke Maven from a command terminal as a test with the following instruction:

mvn -version

If the configuration is done correctly, we can invoke Maven from a command terminal as a test with the following instruction:

You can continue the tutorial with the next step installation of a Java editor.

Configure Apache Maven for Mac OSX

Configuring Maven for Mac OS is as simple as it is for Windows. Just unzip the downloaded Zip file from the previous step and place the files in a directory. For example, in the directory where the JDK files are stored: /opt/apache-maven-version. Note the full path because it will be needed in the next step.

Once the files are unzipped, you will need to create the MAVEN_HOME environment variable pointing to the aforementioned path, the base of the installation. Using this variable allows you to switch from one Maven distribution to a more updated version without changing all the references scattered throughout the projects.

export $MAVEN_HOME=/opt/apache-maven-<version>

Lastly, add the Java binaries path to the Path environment variable so that we can invoke Maven with the mvn command from any directory:

export PATH=$MAVEN_HOME/bin:$PATH

If the configuration is done correctly, we can invoke Maven from a command terminal as a test with the following instruction:

mvn -version

Remember that to make the changes permanent and avoid having to invoke export in each terminal session, you can add both statements to the terminal initialization file located at ~/.profile.

You can continue the tutorial with the next step installation of a Java editor.

Next Step - Install an IDE

To install the editor, remember that you need to have the Java JDK to edit, compile, and run a Java application. Additionally, we'll need a good programming editor to simplify Java file editing tasks. Lastly, it's advisable to include the git version control system in our project to avoid losing even a single comma due to errors.

File Organization

Maven defines that every Java project, whether it's for building a library or an application, must have the following directory structure in the file system:

  • pom.xml: description file, located at the root of the project. It indicates its name, the location it will have in the binary repository, the dependencies needed for compilation, execution, or running tests. It also specifies if plugins will be used.
  • src/main/java: directory where Java files of the project will be located, compiled, and included in the resulting binary. From this directory, Java files' packages are considered. For example, the source file of the org.project.Person class will be located at src/main/java/org/project/Person.java.
  • src/main/resources: allows adding resources that will also be included in the resulting binary but should not be compiled. For example, files with .properties, XML, or image extensions.
  • src/test/java: directory to place Java sources that will only be used in the execution of unit tests. The content of this directory will not be packaged in the final binary.
  • src/test/resources: necessary if other resources such as XML or CSV files with test data to verify algorithms are used in the execution of tests. The included files will not be packaged in the final file.
  • target/classes: this directory will store the Java classes resulting from the compilation of sources stored in src/main/java.
  • target/<project.jar>: typically projects will generate a binary with the content of target/classes plus src/main/resources in a single file packaged with the jar extension. If the project is an application, it will also contain all dependencies within it so that everything needed is available when running the application, forming a file called a fat-jar.

Practically all Java programming editors work perfectly with projects organized as Maven indicates. It can be considered that it has become a de facto standard. Editors automatically process the pom.xml file to consider the necessary dependencies and adjust the project configuration according to what is specified in the file.

Build Phases

Once the organization of the source files constituting a project has been defined, the next step is to invoke Maven to carry out the project's construction process. Maven is aware of dependencies between modules, so if it is a modular project, the construction order of the modules will be in the correct order to satisfy dependencies. The construction of each individual module is done in the same way as for a simple project. Therefore, whether for a module or for a simple project, Maven will try to build the module or project, always going through the following phases in the indicated order:

  1. validate: validates that the project is correct and that all necessary information is available according to the POM specifications.
  2. compile: compiles the project's source code by inspecting all src/main/java directories, storing the .class files in target/classes.
  3. test: tests the compiled source code using the unit testing framework specified in the POM, typically JUnit. In this phase, the execution of all tests is launched. If the result of any of them is incorrect, the construction is interrupted.
  4. package: collects the compiled code and packages it in its distributable format, usually as a file of the type <application>.jar.
  5. verify: executes any checks on the results of integration tests to ensure that quality criteria are met.
  6. install: installs the package in the local repository, to be used as a dependency in other local projects.
  7. deploy: copies the built binary to the remote repository, to share it with other developers and projects. This phase requires specifying the URL of the repository where to deploy, as well as the credentials to use if necessary.
  8. clean: (optional) If invoked manually, Maven will delete all resources generated during compilation and packaging, deleting the target directory.
  9. site: (optional) produces an HTML report about the project showing the Javadoc API documentation and statistics according to the analysis tools configured.

In most cases, it will be sufficient to launch the execution of Maven stopping at some point before deploy if working locally. For example, often it will be enough to execute package if it is a simple application or install if it is the update of some module used by another application. To indicate how far the construction of a project should be executed, on the command line located in the directory where the pom.xml is hosted, Maven will be invoked using the mvn command specifying the phase where to stop:

    # update target/classes
    mvn compile

    # install binary into local repository
    mvn install

    # both steps
    mvn compile install

    # clean resources before install
    mvn clean install

No matter which phase is specified, if it goes through package, Maven will make the binary available locally located in the target directory of the corresponding project or module.

Dependency Management

One of the greatest benefits of using Maven is its excellent dependency management tool together with the vast catalog of libraries it offers publicly. All of them without any usage cost. Maven comes preconfigured with public repositories where most of the Java ecosystem's Open Source libraries are deployed. To use any of them, simply specify a new dependency in the project's POM.

When the project requires a dependency, Maven will look for it in the local repository. If the library is not stored there, typically as a .jar file, Maven will attempt to download it from the internet by searching in public repositories. If found remotely, it will save a local copy for future use. The default directory of the local repository is usually <user_home>/.m2/repository. Although an alternative path can be specified in Maven's configuration file <user_home>/.m2/settings.xml. As long as not specified otherwise, all dependencies from all projects will be stored in that directory. Consequently, several gigabytes of information can easily accumulate as the usage of different libraries and versions progresses across projects. Users are free to delete the contents, causing Maven to re-download the necessary dependencies.

Project dependencies should be placed within the <dependencies> section. It should be noted that these dependencies can have different usage scopes called scopes. The scope is indicated in the <scope> attribute of the XML and allows for the separation of dependencies needed for compilation from those that will only be required during the application's execution. Maven supports the following scopes:

  • compile: This is the default scope if no other is specified. It refers to ordinary dependencies that are necessary for both compilation and execution. Therefore, they should accompany the final application binary.
  • provided: These are dependencies required for compilation and execution, just like in the compile scope, but the difference is that they do not need to be added to the application binary. It is assumed that these will be provided to the application externally to Maven. This scope is useful when deploying an application on an application server that already has the necessary libraries.
  • runtime: Refers to dependencies not required for compilation but must accompany the final application binary because the program's execution will require some functionality from the cited library.
  • test: Reserved for dependencies that are only required for performing unit test tests, so they are not necessary for compilation or execution. Therefore, they will not accompany the final binary.
  • system: In practical terms, it is similar to compile, with the caveat that the JAR file is provided manually by the programmer, indicating the file path. Maven does not need to resolve it as a dependency using the local repository.
  • import: Used to import all dependencies defined in another POM artifact. Requires that the dependencies be listed in the XML section called <dependencyManagement> of this second POM.

In most cases, it will only be necessary to specify the test scope, as the other compile scope will be applied automatically by Maven in the absence of data. Regardless of the scope, all dependencies must be within the <dependencies> section:

<project ...>
    ...
    <dependencies>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.11</version>
            <scope>test</scope>
        </dependency>
        ...
    </dependencies>
    ...
</project>

The wide variety of dependencies available in Maven makes it difficult for programmers to remember what data to include when adding a library. Additionally, Java is composed of a very active community of developers who frequently release new resources and updates. All of this complicates the task of adding a library or artifact to the project. To facilitate this task, there is a website that offers a user interface designed for programmers. On this website, users can locate and copy dependencies comfortably into the project's POM. This website uses the same public repositories as Maven, indexing all their content:

The website offers usage statistics for the main libraries, which can be useful for discovering other projects to consider in future developments. As projects grow, the list of dependencies also grows, and by extension, the transitive dependencies of the included libraries. Sometimes, conflicts may arise when two dependencies internally use different versions of the same library. Finding and resolving this situation requires non-trivial research and searches on the internet. One option that aids in diagnosis is through Maven. You can request Maven to display information on how it resolved direct and transitive dependencies, indicating which version of each is being applied.

To view the resolution result of the requirements, the following command must be executed:

mvn dependency:tree

This command will print to the console the resolution of dependencies used during the compilation and packaging of the application. It is very useful when troubleshooting compatibility issues between used libraries or abnormal behaviors at runtime.

First Application with Maven

The simplest way to create a first application with Maven and Java is to invoke the Maven wizard to create a project skeleton. To do this, we need to provide the group and the project name (artifactId) to the wizard, which can be invoked from the terminal.

For example, if we want to create a project with the group: org.eadp and artifact: my-app, we will execute the following command:

mvn archetype:generate \\
    -DarchetypeArtifactId=maven-archetype-quickstart \\
    -DinteractiveMode=false \\
    -DgroupId=org.eadp \\
    -DartifactId=my-app

The execution of a Maven archetype is nothing more than the application of a default template that generates an application skeleton, creating the content within the directory with the same name as the one given to the project through the artifactId variable.

The project can be imported without any problem from any Java programming editor with Maven support. Try building the project with mvn package to see what happens.

The generator creates an initial test as a template so that the programmer has a quick reference on how to create tests and thus apply a test-driven development methodology. You can run the tests from the command line with mvn test.

In any case, we recommend that you familiarize yourself with the use of your preferred Java IDE, which will greatly simplify the tasks of building, debugging, testing, and any other daily tasks of the programmer.

Leave your comments below or write to us to share your experience or to improve this content. Greetings!

Stay Connected

Newsletter

Stay up to date with the latest in technology and business! Subscribe to our newsletter and receive exclusive updates directly to your inbox.

Online Meeting

Don't miss the opportunity to explore new possibilities. Schedule an online meeting with us today and let's start building the future of your business together!

  • :)
  • :0
  • :D
  • ;)
  • :]