Skip to content

The very foundations of enterprise java kotlin projects

In the previous chapter we discussed the language and how it`s very dependent on the java/jvm ecosystem.

Now we go through the tools to manage more complex projects which make use of third party libraries, but first a bit of history.

The history the way i remember it

Classic software development always needed tools to save us from the tedious work of compile code in the proper way.

For C there was Make, then Automake, then other obscure ways of indirection.

For java, as the legends says, people where unable to understand how make works then they created Ant. That made easier to build and package complex projects, yet it still was up to the programmer to carefully pick the right version of each third party libraries by hand and put in a "lib" folder.

Taking inspiration from tools like apt, Maven born and took the java development ergonomics even further by making the dependency management an automatic process, all you needed to provide was the artifact coordinates.

The maven registry become insanely huge and the adoption of it as the default way of create a java project skyrocket.

Several new tools appeared over the time trying to replace maven because xml wasn't sexy anymore and the most prominent tool on that field is gradle.

All alternative tools still make use of maven's registry and it's coordinate system of dependencies.

IDE support for both tools is prime nowadays, with intellij, eclipse, netbeans, vscode and others offering support to maven and gradle out of the box or via plugin.

Maven setup

In order to manage a project with maven, you need to install the command line tool. For mac, use brew:

brew install maven

For linux, use sdkman:

sdk install maven

Then you can use the following command line(s) to create a maven project:

bash
mvn archetype:generate \
  -DgroupId=com.mycompany.app \
  -DartifactId=my-app \
  -DarchetypeArtifactId=maven-archetype-quickstart \
  -DarchetypeVersion=1.4 -DinteractiveMode=false

This hideous command does the following:

Notes on standard folder structure

In the initial sample projects we provided, all you needed to do to have a project was a folder and an idea. Little by little, we started to organize things (i.e. a src folder, build output folder). If we kept that pace, we might ended up reinventing the current maven folder layout.

The maven project folders became a standard on java (and kotlin by inheritance) projects even on non-maven projects. So, get used to it.

Notes on pom.xml

The pom.xml generated is, by the time this material was written, outdated. I mean extremely outdated. It suggests the use of java 1.7. You must manually update the java version once the project is created.

Also remember, maven born to java projects, other languages supported by jvm are available for maven projects via maven plugins.

In the end, instead of use the command line directly, the common practice to create maven projects, kotlin or not, is to keep a sample pom.xml file already configured and just rename a few things, and create the standard maven directories by hand.

See the sample maven project for further details.

Gradle setup

In order to provision gradle projects, you start by installing it.

On linux (using sdkman):

bash
sdk install gradle

On mac (using homebrew):

bash
brew install gradle@8

On windows:

good luck!

Then you can create a project using the following command (it needs at least gradle 8.6 to work properly):

bash
mkdir project-008-sample-gradle
cd project-008-sample-gradle
echo "no"| gradle init \
  --type kotlin-application \
  --dsl kotlin \
  --test-framework kotlintest \
  --package project008 \
  --project-name project-008-sample-gradle \
  --no-split-project  \
  --java-version 17

This extremely hideous command will generate for you a kotlin-ready project managed with gradle.

Unlike the maven version, no need to manual changes in the config file after project creation except for new dependencies.

The resulting project has a slightly distinct folder structure:

bash
project-008-sample-gradle
├── app
   ├── build.gradle.kts
   └── src
       ├── main
   ├── kotlin
   └── project008
       └── App.kt
   └── resources
       └── test
           ├── kotlin
   └── project008
       └── AppTest.kt
           └── resources
├── gradle
   ├── libs.versions.toml
   └── wrapper
       ├── gradle-wrapper.jar
       └── gradle-wrapper.properties
├── gradlew
├── gradlew.bat
└── settings.gradle.kts

The equivalent (more or less) of pom.xml in gradle projects is the build.gradle (or build.gradle.kts, if you specify --dsl as kotlin instead of groovy) file. It has a dependencies section very similar to what maven has, but uses some exotic ways to represent the libraries coordinates.

Instead of xml, it uses groovy (or kotlin itself!) language to declare project configurations. This is a good thing, technically. Programming languages instead of markup languages are supposed to be easier to the programmer eye, therefore easier to maintain. Also less brain rewire and context switching when jumping from source code and project configuration code.

Wrapper scripts

Wrapper scripts allow you to distribute a reproducible build setup by making sure not only of the dependencies versions are right but also the maven or gradle runtime versions are the same too.

They are useful because the gradle or maven setup on local machine can be tricky in many ways, so it's a good strategy to work with those kind of scripts.

In gradle example you might already notice the wrapper script: it's the gradlew (or gradlew.bat if you're on windows) file.

When it does not exist, there is a gradle task to create the wrapper.

Maven has its own task as well.

So, when you have the wrapper properly configured, instead of do:

bash
gradle build

You do:

bash
./gradlew build

Or, with maven:

bash
./mvnw clean compile package

We already saw some of them on those projects, but list them properly with links, so it gets easier to check them out when the time to use one comes:

purposegradlemaven
kotlin supportlinklink
repackage with dependencieslinklink
ease code execution in developmentlinklink
test coveragelinklink
database migrationslinklink
spring-boot supportlinklink

Multi module projects

Using maven or gradle also makes possible to declare not only external dependencies but also local modules.

You can read more about this practice here for gradle and here for maven.

One interesting side effect of multi modules projects is that, as long as the output of each module remains compatible with the jvm, they can be written in any language. it makes possible, for example, to feature java, kotlin, groovy and more in one single codebase.

Using java libraries and code from kotlin code and vice versa

This benefit can be achieved using multi modules but also in the same project. The module itself has distinct source sets for each language, for example this project.

Further reading

This is the minimum to know to handle projects using those tools.

What? Which one is better?

Hard question.

  • Gradle has lots of attention due jetbrains dedication to it.
  • Maven is the first one, who created the coordinate system for dependencies.
  • Gradle eats more memory, spawns a daemon for faster incremental builds.
  • Maven is faster for single builds.
  • Gradle is buggier than Maven.
  • Maven is harder to extend.
  • Gradle has easier setup for other registries than maven central.

In the end, there is no way to enter enterprise JVM-based development without know both, because all projects out there are using that.