Matt Howlett

Matt Howlett

every blog should have a tagline

Basic Java/Maven Workflow


This is just a notes-to-self blog post that documents some basic processes related to writing simple Java applications. I need to go through all this somewhat regularly, but not regularly enough that I remember the details off the top of my head, so it's time to write it down.

Maven seems the most widely used build/dependency management tool. In practice, I've found it easier to leverage Maven than try and work with java and javac directly, even for quick little test projects. As a bonus, it scales to even the most complex of scenarios.

I avoid using IntelliJ for small projects because I don't want to add another layer of complexity and I like the VS Code editing experience better. The Java intellisense etc in VS Code is pretty good these days and so overall I think it's a better solution for small projects.

Generating a New Maven Project

To create a new project:

mvn archetype:generate

You can specify various parameters as arguments, or if you don't you'll be prompted for what's needed. That's most convenient here if you're not trying to automate something.

The first question is which project archetype (template) to use. The default is 1383 (maven-archetype-quickstart) which is perfect for a simple console application. You'll be asked for what version of the archetype to use - the default here is 1.4, go with that.

Next, you'll need to specify the project groupId (e.g. com.mhowlett) which together with the artifactId (specified next, e.g. test-project) is intended to uniquely identify your project across all projects. The groupId and artefactId are what you use to specify your project as a dependency in another project's pom.xml file. The artifactId is also the name of the jar file minus the version suffix. After groupId and artifactId, you'll be asked for a version, which defaults to 1.0-SNAPSHOT. That's fine.

Finally, you'll be asked for a package name which will be used to generate the initial directory structure of your project. Usually you should make this align with the groupId, but it doesn't need to. A package is simply a namespace. A given .jar file can contain any number of packages.

If you want Java 8 (rather than Java 7), update the maven.compiler.source and tags in the generated pom.xml to 1.8.

Building and Installing

You can build your package with:

mvn package

You can 'install' your package in the local cache, making it accessible as a dependency for other local projects with:

mvn install


Add the following to the generated pom.xml file under build\plugins:


(replacing the value of mainClass appropriately).

Now you can run your application with the following:

mvn exec:java

Local .jar Dependencies

I sometimes need to specify a local fat jar dependency (which in turn contains shaded dependencies). There are various ways to do this, but the method I've been using is to install the fat jar in the local maven cache:

mvn install:install-file -Dfile=the-jar-file.jar -DartifactId=the-artifactid -Dversion=<version> -Dpackaging=jar

and then just specify the dependency as normal in the pom.xml file.

Note that I'm using an artifactId for the fat jar which is different from the original jar's artifactId.

Creating a fat .jar

Confluent's JMS Client installation instructions provide a good example of how to create a fat jar with shaded dependencies.

List/Extract the contents of a .jar

Sometime I need to inspect the contents of a .jar for debugging purposes. To do this:

jar tf jar-file

And to extract the contents of a .jar:

jar xf jar-file

That's it! Already more than I really wish I needed to know about the Java ecosystem :-).

Side note: Java could learn a thing or two from C#/.NET Core here - the Java way seems overly complicated by comparison.