Skip to content

Instantly share code, notes, and snippets.

@george-hawkins
Last active April 3, 2021 15:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save george-hawkins/99009187e124a8c16d8d986222a7b097 to your computer and use it in GitHub Desktop.
Save george-hawkins/99009187e124a8c16d8d986222a7b097 to your computer and use it in GitHub Desktop.
Reference Kotlin pom
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.example</groupId>
<artifactId>foobar</artifactId>
<version>1.0-SNAPSHOT</version>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <!-- https://stackoverflow.com/a/3018152/245602 -->
<java.version>11</java.version> <!-- Also picked up by Spring. -->
<maven.compiler.source>${java.version}</maven.compiler.source>
<maven.compiler.target>${java.version}</maven.compiler.target>
<kotlin.compiler.jvmTarget>${java.version}</kotlin.compiler.jvmTarget>
<kotlin.version>1.4.32</kotlin.version>
<kotlin.code.style>official</kotlin.code.style>
<junit-jupiter.version>5.7.1</junit-jupiter.version>
<logback.version>1.2.3</logback.version>
<surefire.version>2.22.2</surefire.version>
<maven-compiler.version>3.8.1</maven-compiler.version>
</properties>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib-jdk8</artifactId>
<version>${kotlin.version}</version>
</dependency>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-test-junit5</artifactId>
<version>${kotlin.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>${logback.version}</version>
<optional>true</optional> <!-- Don't force on downstream projects. -->
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
<dependency>
<groupId>org.junit</groupId>
<artifactId>junit-bom</artifactId>
<version>${junit-jupiter.version}</version>
<type>pom</type>
<scope>import</scope>
</dependency>
</dependencies>
</dependencyManagement>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-surefire-plugin</artifactId>
<version>${surefire.version}</version>
</plugin>
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<configuration>
<args>
<arg>-Xjvm-default=enable</arg> <!-- https://kotlinlang.org/docs/java-to-kotlin-interop.html#default-methods-in-interfaces -->
<arg>-Xjsr305=strict</arg> <!-- https://kotlinlang.org/docs/java-interop.html#jsr-305-support -->
</args>
</configuration>
<executions>
<execution>
<id>compile</id>
<goals>
<goal>compile</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/main/kotlin</sourceDir>
<sourceDir>${project.basedir}/src/main/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
<execution>
<id>test-compile</id>
<goals>
<goal>test-compile</goal>
</goals>
<configuration>
<sourceDirs>
<sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
<sourceDir>${project.basedir}/src/test/java</sourceDir>
</sourceDirs>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>${maven-compiler.version}</version>
<configuration>
<compilerArgs>
<!-- https://docs.oracle.com/en/java/javase/14/docs/specs/man/javac.html -->
<arg>-Xlint:unchecked</arg>
</compilerArgs>
</configuration>
<executions>
<!-- Replacing default-compile as it is treated specially by maven -->
<execution>
<id>default-compile</id>
<phase>none</phase>
</execution>
<!-- Replacing default-testCompile as it is treated specially by maven -->
<execution>
<id>default-testCompile</id>
<phase>none</phase>
</execution>
<execution>
<id>java-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal>
</goals>
</execution>
<execution>
<id>java-test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>testCompile</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
@george-hawkins
Copy link
Author

george-hawkins commented Apr 2, 2021

Optional extras

I've included logback as a dependency above as having an SLF4J implementation is practically mandatory.

Other dependencies that I'd usually consider as fundamental:

Even if I'm not using Spring, I often leave it to Spring to define a coherent set of compatible dependency versions by using it as the parent pom:

 <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.4.4</version>
</parent>

I used to use the BOM approach to pulling in versions like this but using the Spring parent pom has other worthwhile advantages (again, even if you're not using Spring) - in particular, it cleans up some bizarre defaults and the like in a number of core plugins that don't make any sense anymore (if they ever did) but have been kept that way to avoid breaking people who rely on these historical oddities.

Also worth considering as a default plugin is JoCoCo - for a friendlier (if ad-riden) introduction see the Baeldung intro to JaCoCo.

<plugin>
    <groupId>org.jacoco</groupId>
    <artifactId>jacoco-maven-plugin</artifactId>
    <version>${jococo.version}</version>
    <executions>
        <execution>
            <id>default-prepare-agent</id>
            <goals>
                <goal>prepare-agent</goal>
            </goals>
        </execution>
        <execution>
            <id>default-report</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>report</goal>
            </goals>
        </execution>
    </executions>
</plugin>

@george-hawkins
Copy link
Author

george-hawkins commented Apr 3, 2021

I added the junit-bom in the dependencyManagement section despite just having just onedirect JUnit dependency whose version tag could be dropped as a result. This resolved very odd failures when running mvn test (the Surefire plugin would exit with strange exceptions that seemed to be the result of NoClassDefFoundError). You can get more informative output from Maven with:

$ mvn -DforkMode=never -e clean test

I tried various things to resolve this, including many of the suggestion in this SO answer, but in the end it was adding the junit-bom block that did the trick.

I also added maven-surefire-plugin to the plugins section so I could make sure that the latest version of the plugin is used. If I was using the spring-boot-starter-parent parent pom, I don't think this would be necessary (and perhaps also the junit-bom would be unnecessary too).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment