Skip to content

Instantly share code, notes, and snippets.

@OndraZizka
Last active April 16, 2025 09:16
Show Gist options
  • Save OndraZizka/0ae6a2914116a8ba118279511935d49a to your computer and use it in GitHub Desktop.
Save OndraZizka/0ae6a2914116a8ba118279511935d49a to your computer and use it in GitHub Desktop.
Maven super-short intro.

Maven super-short intro.

Note

Maven is declarative, not procedural. By default it is in XML, but you can write it in other languages.* We will use YAML.

 

Tip

Maven works on a principle of a “tree of trees” of build configuration overlaid over each other, which then create an effective tree - so called POM (project object model).

Tip

There is a tree of modules, which usually more less correlates to the directory structure; each module contributes another overlay POM to what it inherits from the ancestors.

Let’s have a project. It has a root and 1 module.

  • itsspush-root
    • itsspush-server

Each of these modules has a POM, project object model, which is a tree of configuration.

Imagine 2 YAMLs. Let’s call them itsspush-root and itsspush-server. (For brevity, these snippets are not full POMs, and the project is added for better optics.)

project:
  groupId: com.mycompany.itsspush
  artifactId: itsspush-root
properties:
  db_user: abc123
project:
  artifactId: itsspush-server

Now let’s put them in relation: Make the itsspush-root to be the parent of itsspush-server.

project:
  parent:   itsspush-root      <-- NEW
  artifactId: itsspush-server

During a build, Maven merges these trees for each node. Parents are overlaid with children.

Therefore, the effective POM of itsspush-server results into:

project:
  groupId: com.mycompany.itsspush
  parent:   itsspush-root
  artifactId: itsspush-server
properties:
  db_user: abc123

 

Tip

The effective POM controls executions of plugins - when, how, and on what they act.

The pom.xml files contain 2 kinds of information: General project description, like artifactId, and plugin configurations. The General description may be used by plugins as default values.

Otherwise, the plugins are configured in their respective plugin section.

build:
  plugins:
    plugin: 
      artifactId: maven-flyway-plugin       
      configuration:
        jdbcUrl: ...
    plugin: ...

Like everything, these values are also merged - inherited from the parent, and overlaid by the children. That means, a plugin which executes in a parent also executes in all children (unless an overlay disables that).

Depending on project: / packaging: ..., some default plugin executions are pre-set. E.g. packaging: jar provides Java compilation via maven-compiler-plugin, etc.

 

Tip

Maven handles the aspect of dependencies, which determines the class paths, but also the order of the modules during build.

The library dependencies point to an artifact in some repository, and are usually added to a compilation or runtime class path.

The “project dependencies” point to a module within the project, and besides class path, they are used to compute the order of modules in a build.

 

Tip

Maven has a default list of build phases.

Being a build tool, Maven designers identified a list of generic build phases, which mostly fits any project module build.

The key word is module: Usually, when you feel these phases are not enough, you should split your module into sub-modules. This is one of the most useful effects of Maven on the quality of builds.

 

Tip

Properties

The POM also contains properties, a Map<String, String>. And like everything, it is overlaid by child POMs.

Properties can be used (almost) anywhere where you can place text - including other property values.

Propeties can be defined in the pom.yaml, as env vars, in a properties file, as a CLI input, or even dynamically by plugins. They overlay in that order.

properties:
  db.user: granit

mvn … -Ddb.pass: myPasswd123

 

Tip

Profiles

One more overlay mechanism is a profile. Within one pom.yaml, multiple profiles may be defined; they contain parts of the module’s POM. Upon activation, all the active profiles are merged into the module’s POM, in the order of appearance in the file. (The resulting merged module’s POM then serves as what is passed to the children.)

profiles:
  - id: useGranit
    plugins:
      artifactId:  docker-maven-plugin
      ## ... the rest of config to build, start and stop Granit Docker image.

mvn … -PuseGranit

 

Tip

Local config: ~/.m2/settings.xml

To keep your local stuff local, certain things go to profiles in settings.xml: Passwords, user names, local paths, keys, etc.

profiles:
  - id: nexxiot
    properties:
      jfrogRepo.key: ey...
      jfrogRepo.url: https://nexxiot.jfrog.com/...        

 

Note

That’s it 😄

Seriously. There’s not much more. The concepts above are incredibly powerful, and when you wrap your head around them, you can solve 99.5 % build needs in a concise way, not repeating yourselves; and 90 % will be elegant.

 

* Alternative syntaxes are possible via Maven Polyglot. Some tools may only work with XML.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment