What is Polyglot Maven?

Most people assume that their Maven build logic should always be written in XML. What most people don’t know is that Maven allows extending the build tool itself using core extensions, which were significantly improved in Maven 3.3.1.

Core extensions as the name suggests allow you to extend the core functionality of Maven itself. Note that you shouldn’t confuse these core extensions with extensions from plugins.

An example of such a Maven core extension is Polyglot Kotlin which allows you to write your POM in Kotlin instead of XML. It was recently improved so it uses the newest Kotlin script engine. A huge benefit of using this scripting engine is that it adds auto-completion support.

This makes the experience similar to writing a Gradle build script (for those that have done that).

The Polyglot Kotlin core extension is part of the Polyglot Maven project. It consists of multiple core extensions that allow you to write the POM (Project Object Model) in languages other than XML. Currently supported languages are Clojure, Groovy, Java, Kotlin, Ruby, Scala and YAML.

Why should I use Polyglot Maven instead of XML?

Now you might ask yourself: why would I want to write my build script in something other than XML? Personally I find the XML format to be too restrictive and verbose for a build tool. Using an actual programming language such as Kotlin gives you a considerable amount of flexibility and expressiveness in writing your build logic.

The only danger of using Kotlin is that your POM quickly becomes too complex for others to understand.

A use-case where you would want such amount of flexibility is when you’d like to use a dynamic version. Recently the use of semantic versioning is gaining popularity. Implementing semantic versioning correctly is hard though. You have to make sure that everyone in your team understands when to increment either the major, minor or patch version when releasing.

Suppose that instead of setting the version manually with each release you want to automatically increment your major, minor or update version based on the Git commit history. This would be incredibly hard, maybe even impossible, to do in XML.

You could of course write a Maven plugin for that, but it will probably only work for the project you are working on. It is not as expressive as directly writing such logic in your POM. Allow me to demonstrate:

How do I use Polyglot Maven?

For this example I created a simple REST service containing ToDo tasks.
The sources of this example can be found on GitLab.

First we need to apply the appropriate core extension so Maven will pick up a POM written in Kotlin. To do this create the file .mvn/extensions.xml and add the following:

Then we need some rules to decide when to increment which part of the version:

    • the major if there is a commit message containing ‘BREAKING CHANGE’
    • the minor if there is a commit message starting with ‘feat’
    • the patch in all other cases

Note: these commit message checks are inspired by the Conventional Commits specification.

Implementing the above checks in Kotlin is not that complicated.
Here is the resulting pom.kts file:

Building this project with ‘mvn install’ will automatically select the correct next version based on the latest git commit messages.

Running ‘mvn deploy’ will first upload the artefacts and then tag the current HEAD with the next version as tag name.

Enabling Kotlin auto-completion in your IDE when using Polyglot Maven

For auto-completion to work the polyglot-kotlin JAR and its dependencies must be on the compile classpath so IntelliJ IDEA will index them. The easiest way to achieve this without changing your project’s dependencies is to add it as a global library.

To do this open Project Structure (Ctrl+Alt+Shift+S) -> Global Libraries -> click the + sign and choose From maven....

Fill in io.takari.polyglot:polyglot-kotlin:0.4.2, check the Sources checkbox and press OK.
Add the global library to your (IntelliJ IDEA) module and auto-completion should work.

Give it a go – and let me know how it works for you?