Tuesday, August 22, 2023

Maven for ANTers

Coming from a build tool like ANT, it can be pretty frustrating for developers to understand maven. It seems to be doing too many unspecified things, too rigidly. This article tries to understand maven from that perspective.

So here's a quick summary :

  1. Maven executes Goals, just like Ant has targets.
  2. In addition, maven has Phases, each phase being a list of goals. We can also tell maven to execute one or more phases, and then each phase will execute the goals grouped under it. Phases themselves have an order, so that if we execute a given phase, the phases coming before that in the predefined order will be executed first.
  3. The default phases are validate, compile, test, package, verify, install, deploy.
  4. Each maven execution run happens in a lifecycle, which has phases under it. The default lifecycles are defaultclean and site
  5. We can create and define our custom goals. These are packaged in a Plugin.
  6. Maven also allows us to specify and manage dependencies of the project.
  7. Maven resources have a groupId, artifactId and version.
  8. Maven provides for a repository to fetch/store the artifacts. A central maven repository is the default .Also, maven keeps a local repository on the system where its run, to avoid fetching from the remote repository each time.

 

See also https://www.baeldung.com/maven-goals-phases


Read these links first for a basic understanding :
https://maven.apache.org/guides/introduction/introduction-to-the-lifecycle.html

In ANT, we specify tasks and their dependencies. We can execute a specific task, and only that, along with its specified dependent tasks will be executed. But this also means that tasks like clean, compile, generate, copy, package, install, deploy etc have be specified in details for all projects, along with config like source, staging, target dirs etc. Also external dependencies like jars have to be managed, along with their versions.  These may be common amongst multiple projects. Should we check these into source control, or have a separate common location ? What if we want to add a common functionality to all builds ? How do we name and version output artifacts ?

Maven tries to answer these questions. It tries to provide a standard way to execute projects, by promoting convention over configuration :

  • Standardized project directory structure. e.g. The src/main/java,  src/main/resources src/test etc
  • Naming conventions for articfacts using groupid, artifactid, version
  • Providing a dependency configuration, and a repository mechanism to store and access needed dependencies
  • Out-of-the box implementation of standard build lifecycle, so that a project can be build with minimum configuration
  • An inheritance mechanism, so that a build may be shared amongst multiple projects, each overriding only the parts needed.
  • Profiles to have different builds for different case, e.g we might just need compile in dev mode, and the full jar with dependencies may have to be built in production mode.

So if we have a simple java project with no dependencies, then a minimal pom with just the groupid, artifactid and version id will be able to build the project from clean to deploy.

Maven works with lifecyles, phases and goals. It has default implementations of these. We can also create our own lifecycles, which is a list of phases, in order. Then there are goals, that execute in a particular phase which do the actual work. e.g. in the default lifecycle, the install phase has a goal install:install.

Goals are usually implemented using java classes called plugins. When creating plugins, we can specify what phase the plugin should execute, tho its not mandatory. The phase in which a plugin executes can also be specified via the build configuration, and this will override the default.

What can we execute with the maven command ?  

A list of mixture of phases and goals. Whatever phases are specified, all the phases before them in the life cycle will be implicitly executed.
However, thats not the case with goals, only the specified goals will be executed.

e.g. we can execute just the install goal using mvn instal:install, instal:install being the name of the goal in the install phase. Earlier phases will not be run. However, it can cause problems like in this case, since this goal looks for the anme of the output jar to install in the execution context, which is missing. In this case, it can be remedied by also installing the jar:jar goal before, so that it gets the jar name.

What does the maven build file consist of ?


  1. The groupid, artifactid and version id of the project being built, this the minimal info needed.
  2. The list of dependencies needed by the project.
  3. The list of dependency repositories, if using any other than the standard maven one.
  4. The list of repositories if any, to deploy/publish the final artifact( usually jar, war etc)
  5. The build section to use and configure non-standard maven plugins, in which phase and with what params are they to run. Similarly to customise/change execution of the standard maven plugins.
  6. A profiles




No comments:

Post a Comment