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:
For linux, use sdkman:
Then you can use the following command line(s) to create a maven project:
mvn archetype:generate \
-DgroupId=com.mycompany.app \
-DartifactId=my-app \
-DarchetypeArtifactId=maven-archetype-quickstart \
-DarchetypeVersion=1.4 -DinteractiveMode=falseThis hideous command does the following:
- create a folder called my-app
- create a standard maven folder structure to organize your code
- create a pom.xml file to save project configurations
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):
sdk install gradleOn mac (using homebrew):
brew install gradle@8On windows:
good luck!
Then you can create a project using the following command (it needs at least gradle 8.6 to work properly):
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 17This 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:
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.ktsThe 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:
gradle buildYou do:
./gradlew buildOr, with maven:
./mvnw clean compile packagePopular plugins
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:
| purpose | gradle | maven |
|---|---|---|
| kotlin support | link | link |
| repackage with dependencies | link | link |
| ease code execution in development | link | link |
| test coverage | link | link |
| database migrations | link | link |
| spring-boot support | link | link |
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.