Skip to content

update: update Compile Kotlin and Java sources in Maven #4785

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 3 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
128 changes: 109 additions & 19 deletions docs/topics/maven.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,14 +56,30 @@ specify the ID and URL of each repository in the `<repositories>` element:

## Set dependencies

Kotlin has an extensive standard library that can be used in your applications.
To add a dependency on a library, include it in the `<dependencies>` element:

```xml
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlinx</groupId>
<artifactId>kotlinx-serialization-json</artifactId>
<version>%serializationVersion%</version>
</dependency>
</dependencies>
```

### Dependency on the standard library

Kotlin has an extensive standard library that you can use in your applications.
To use the standard library in your project, add the following dependency to your `pom.xml` file:

```xml
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-stdlib</artifactId>
<!-- Uses the kotlin.version property
specified in <properties/>: -->
<version>${kotlin.version}</version>
</dependency>
</dependencies>
Expand All @@ -73,13 +89,56 @@ To use the standard library in your project, add the following dependency to you
> * 1.8, use `kotlin-stdlib-jdk7` or `kotlin-stdlib-jdk8`, respectively.
> * 1.2, use `kotlin-stdlib-jre7` or `kotlin-stdlib-jre8`, respectively.
>
{style="note"}
{style="note"}

### Dependencies on test libraries

If your project uses [Kotlin reflection](https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.reflect.full/index.html)
or testing facilities, you need to add the corresponding dependencies as well.
The artifact IDs are `kotlin-reflect` for the reflection library, and `kotlin-test` and `kotlin-test-junit`
or testing frameworks, add the relevant dependencies.
Use `kotlin-reflect` for the reflection library, and `kotlin-test` and `kotlin-test-junit`
for the testing libraries.

For example:

```xml
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-reflect</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
```

### Dependency on a kotlinx library

Depending on the kotlinx library, you can either add the base artifact name or the name with a `-jvm` suffix. Refer to
the library's README file on [klibs.io](https://klibs.io/).

For example, to add a dependency on `kotlinx.coroutines`:

```xml
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlinx</groupId>
<artifactId>kotlinx-coroutines-core</artifactId>
<version>%coroutinesVersion%</version>
</dependency>
</dependencies>
```

To add a dependency on `kotlinx-datetime`:

```xml
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlinx</groupId>
<artifactId>kotlinx-datetime-jvm</artifactId>
<version>%dateTimeVersion%</version>
</dependency>
</dependencies>
```

## Compile Kotlin-only source code

To compile source code, specify the source directories in the `<build>` tag:
Expand Down Expand Up @@ -135,25 +194,43 @@ If you need to configure an execution, you need to specify its ID. You can find

## Compile Kotlin and Java sources

To compile projects that include Kotlin and Java source code, invoke the Kotlin compiler before the Java compiler.
In Maven terms it means that `kotlin-maven-plugin` should be run before `maven-compiler-plugin` using the following method,
making sure that the `kotlin` plugin comes before the `maven-compiler-plugin` in your `pom.xml` file:
To compile a project with both Kotlin and Java source files, make sure the Kotlin compiler runs before the Java compiler.
The Java compiler can't see Kotlin declarations until they are compiled into `.class` files.
If your Java code uses Kotlin classes, those classes must be compiled first to avoid `cannot find symbol` errors.

Maven determines plugin execution order based on two main factors:

* The order of plugin declarations in the `pom.xml` file.
* Built-in default executions, such as `default-compile` and `default-testCompile`, which always run before user-defined executions,
regardless of their position in the `pom.xml` file.

To control the execution order:

* Declare `kotlin-maven-plugin` before `maven-compiler-plugin`.
* Disable the Java compiler plugin's default executions.
* Add custom executions to control the compile phases explicitly.

> You can use the special none phase in Maven to disable a default execution.
>
{style="note"}

Here's an example configuration:

```xml
<build>
<plugins>
<!-- Kotlin compiler plugin -->
<plugin>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-plugin</artifactId>
<version>${kotlin.version}</version>
<extensions>true</extensions> <!-- You can set this option
to automatically take information about lifecycles -->
<extensions>true</extensions>
Copy link
Member

@ALikhachev ALikhachev Jun 5, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It seems that actually this <extensions>true</extensions> does not make any sense. According to the previous comments, it could help avoid some configuration, but that does not appear to be true in Kotlin + Java in this particular configuration.

However, if we modify the example to

    <plugins>
      <!-- Kotlin compiler plugin -->
      <plugin>
        <groupId>org.jetbrains.kotlin</groupId>
        <artifactId>kotlin-maven-plugin</artifactId>
        <version>${kotlin.version}</version>
        <extensions>true</extensions>
        <executions>
          <execution>
            <id>default-compile</id>
            <phase>compile</phase>
            <configuration>
              <sourceDirs>
                <sourceDir>${project.basedir}/src/main/kotlin</sourceDir>
                <sourceDir>${project.basedir}/src/main/java</sourceDir>
              </sourceDirs>
            </configuration>
          </execution>
          <execution>
            <id>default-test-compile</id>
            <phase>test-compile</phase>
            <configuration>
              <sourceDirs>
                <sourceDir>${project.basedir}/src/test/kotlin</sourceDir>
                <sourceDir>${project.basedir}/src/test/java</sourceDir>
              </sourceDirs>
            </configuration>
          </execution>
        </executions>
      </plugin>
    </plugins>

we can completely skip the Java plugin configuration and it would just work, thanks to the <extensions> setup. This configuration indeed seems much easier and shows benefit of extensions

Note that I changed execution IDs in this example.

I would suggest introducing something similar to how we show Kotlin/Groovy scripts, aka "tabs" for showing configuration with <extensions>true</extensions> and without it.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, interesting, I tried just copy-pasting the setup (both before any changes and from this PR) on top of pure Kotlin setup – it leads to incorrect configuration when Java code can see Kotlin code, but Kotlin code cannot see Java.

Either removing the extensions setup or removing of the following configuration helps.

<sourceDirectory>${project.basedir}/src/main/kotlin</sourceDirectory>
<testSourceDirectory>${project.basedir}/src/test/kotlin</testSourceDirectory>

With the abovementioned change of execution id, it works fine. That's because setup from extensions creates executions default-compile and default-test-compile

<executions>
<execution>
<id>compile</id>
<id>kotlin-compile</id>
<phase>compile</phase>
<goals>
<goal>compile</goal> <!-- You can skip the <goals> element
if you enable extensions for the plugin -->
<goal>compile</goal>
</goals>
<configuration>
<sourceDirs>
Expand All @@ -163,10 +240,10 @@ making sure that the `kotlin` plugin comes before the `maven-compiler-plugin` in
</configuration>
</execution>
<execution>
<id>test-compile</id>
<goals>
<goal>test-compile</goal> <!-- You can skip the <goals> element
if you enable extensions for the plugin -->
<id>kotlin-test-compile</id>
<phase>test-compile</phase>
<goals>
<goal>test-compile</goal>
</goals>
<configuration>
<sourceDirs>
Expand All @@ -177,21 +254,24 @@ making sure that the `kotlin` plugin comes before the `maven-compiler-plugin` in
</execution>
</executions>
</plugin>

<!-- Java compiler plugin -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.5.1</version>
<version>3.8.1</version>
<executions>
<!-- Replacing default-compile as it is treated specially by Maven -->
<!-- Disable default executions -->
<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>

<!-- Define custom executions -->
<execution>
<id>java-compile</id>
<phase>compile</phase>
Expand All @@ -212,6 +292,16 @@ making sure that the `kotlin` plugin comes before the `maven-compiler-plugin` in
</build>
```

This configuration ensures the following:

* Kotlin code is compiled first.
* Java code is compiled after Kotlin and can reference Kotlin classes.
* Default Maven behavior doesn't override the plugin order.

For more details on how Maven handles plugin executions,
see [Guide to default plugin execution IDs](https://maven.apache.org/guides/mini/guide-default-execution-ids.html) in
the official Maven documentation.

## Enable incremental compilation

To make your builds faster, you can enable incremental compilation by adding the `kotlin.compiler.incremental` property:
Expand Down
2 changes: 1 addition & 1 deletion docs/topics/releases.md
Original file line number Diff line number Diff line change
Expand Up @@ -101,7 +101,7 @@ Alternatively, you can change the version of the `kotlin-maven-plugin` in your `
```

If you have projects created with earlier Kotlin versions, check if you also need to [update the version of any kotlinx
libraries](maven.md#set-dependencies).
libraries](maven.md#dependency-on-a-kotlinx-library).

> To learn more about how to work with Maven in your project, see [Maven](maven.md).
>
Expand Down