March 15, 2016

Just Enough Maven Part 3

This is the third blog post in a series of how to learn just enough Maven so that you're comfortable working with the JVM.

Just Enough Maven Part 1 - Check this out if you need some extra convincing that investing time to learn maven is worth it.

Just Enough Maven Part 2 - Read this for a refresher on how to do basic tasks without maven.

In this post, I'll try describe just enough about maven so you understand what it is. So, let's dive in!

Code that runs Code

So, what is Maven, really? Maven is a really just a java program that knows how to do these three things:

  1. find packages of code
  2. download them
  3. run them

And that's it! That's basically all that the core of maven code knows how to do!

In Maven terminology, each of the packages of code that it knows how to find, download and run is called an "artifact".

An artifact usually consists of a jar file along with some meta data describing what it contains and who created it.

Maven has a nice way of identifying these artifacts so that they can be found easily.

Artifact Names

One of the essential features of maven is that it has to be able to uniquely identify these artifacts. If you write a web app and I write a web app, maven need to be able to disguish between the two.

In order to do so, Maven uses a notion of an artifact "coordinate". A "coordinate" is just a name (a unique identifier) that consists of the following 3 parts:

  1. a group id
  2. an artifact id
  3. a version number

Group ID

The group id usually refers to the person, company, or organization who created the artifact.

For example, I like to use a group id com.upgradingdave for any artifacts I create.

Here are a few other examples:

The jetty server artifact uses a group id of org.eclipse.jetty.

The famous junit test library has a group id of junit.

The code that maven uses to compile source code has a group id of org.apache.maven.plugin (more about this later).

Artifact ID

The artifact id part of the artifact describes what the code actually is (or does).

So for example, I used the artifact id of jdbc to identify some code that I like to reuse whenever I need to access a database. The group id is com.upgradingdave and the artifact id is jdbc. Maven loves xml, so we can describe this artifact like so:

<groupId>com.upgradingdave</groupId>
<artifactId>jdbc</artifactId>
<version>(we'll get to versions in a second)</version>

The jetty server artifact has artifact id of jetty-server. (clever name, i know)

<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>(we'll get to versions in a second)</version>

The junit library uses an artifact id of junit.

<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>(we'll get to versions in a second)</version>

The compiler that maven uses has an artifact id of maven-compiler-plugin. Here's the xml for that one:

<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>(we'll get to this in a second)</version>
<type>(ignore this for now)</type>

Version Numbers

In the world of maven, versions can be whatever you want. You can use 1.0, or 0.11-2, or 0.0.1, or a.b.c.d.e, or 10.2.0.3.0, or whatever!

At the time of this writing, the latest version of jetty is 9.3.7.v20160115. So the full artifact coordinates looks like this:

<groupId>org.eclipse.jetty</groupId>
<artifactId>jetty-server</artifactId>
<version>9.3.7.v20160115</version>

The latest version of junit is 4.12 and so the artifact coordinates looks like this:

<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>

I chose to use a version number of 2.0-SNAPSHOT for my database code, and so the coordinates look like this:

<groupId>com.upgradingdave</groupId>
<artifactId>jdbc</artifactId>
<packaging>jar</packaging>
<version>2.0-SNAPSHOT</version>

Notice the -SNAPSHOT on my version number? That's a standard version naming convention that most people use with maven. Whenever you see a version with -SNAPSHOT on the end, you should treat that artifact like something that is in active/heavy development. In other words, the code inside a SNAPSHOT artifact could (and probably will) change.

SNAPSHOTS are great when you're developing code. But not so good when you want to deploy things in production.

Plugins

One theme I've picked up on over the years of doing software development is that if you can implement something in terms of itself, it's usually a good sign. And Maven is an great example of this.

The core features of Maven are bundled as artifacts.

For example, the code that maven runs to compile your source code inside your projects is a artifact (which was created by maven). It has a group id of org.apache.maven.plugins.

In other words, the core functionality that people normally think of when they think of maven (things like compiling code, running tests, and creating jars) is all bundled up as maven artifacts!

There's no real difference between these artifacts and the artifacts that you will use Maven to create from your own source code.

You could say that Maven uses itself to run itself. Maven truly eats it's own dog food.

Artifacts that maven knows how to run are called Plugins.

For example, the maven compiler plugin is itself a maven artifact.

Remember that, fundamentally, maven is really a program that can find, download and run things. The "things" that maven knows how to find, download, and run are called "plugins".

Putting it all together now: Plugins are maven artifacts that instruct Maven how to do things. For example the maven compiler plugin knows how to compile your source code. They are jar files with some metadata. And so each maven plugin can be uniquely identified with a artifact coordinate (a group id, a artifact id, and a version).

Core Maven Plugins

When people talk about maven, really, what they are normally referring to is a handful of "core" maven plugins that maven will automatically run.

Here's a list of core plugins that maven will automatically download and execute the first time you ever run the mvn command:

  • Maven Compiler Plugin: This one can compile your source code.
  • Maven Resources Plugin: This knows how to copy properties files, images, css, javascript into your class path and can help with configuration and properties files.
  • Maven Surefire Plugin: This is the plugin that knows how to run unit tests and show nice reports
  • Maven jar Plugin: This plugin knows how to copy your compiled bytecode into a jar file.
  • Maven install Plugin: This knows how to package your code up into an artifact (along with meta data so that it can be used with other maven artifacts).

You can find a more detailed list here.

Summary

The core maven code is conceptually very simple. It looks for some core plugin artifacts (jar files with metadata), downloads them and runs them. That's essentially all that maven is from 10,000 foot level.

How does it know where to find these artifacts? And how does it know which order to run them in?

Those are great questions, and it all has to do with the Project Object Model, which I'll describe in the next post.

Tags: tools software java maven