Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you compile Java+Kotlin project using Maven?

Tags:

java

maven

kotlin

I'm trying to compile maven project which has Kotlin classes referencing Java classes. Here's a part of my parent POM:

...

<dependency>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-stdlib</artifactId>
    <version>${kotlin.version}</version>
</dependency>

...

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-compiler-plugin</artifactId>
    <version>${compiler-plugin-version}</version>
    <configuration>
        <source>${java-version}</source>
        <target>${java-version}</target>
        <encoding>${project.build.sourceEncoding}</encoding>
    </configuration>
</plugin>

<plugin>
    <artifactId>kotlin-maven-plugin</artifactId>
    <groupId>org.jetbrains.kotlin</groupId>
    <version>${kotlin.plugin.version}</version>

    <executions>
        <execution>
            <id>compile</id>
            <phase>process-sources</phase>
            <goals>
                <goal>compile</goal>
            </goals>
        </execution>

        <execution>
            <id>test-compile</id>
            <phase>process-test-sources</phase>
            <goals>
                <goal>test-compile</goal>
            </goals>
        </execution>
    </executions>

    <configuration>
        <scanForAnnotations>false</scanForAnnotations>
    </configuration>
</plugin>

And related parts of the child POM:

<dependency>
    <groupId>org.jetbrains.kotlin</groupId>
    <artifactId>kotlin-stdlib</artifactId>
</dependency>

...

<plugin>
    <artifactId>kotlin-maven-plugin</artifactId>
    <groupId>org.jetbrains.kotlin</groupId>
    <configuration>
        <sourceDirs>
            <source>${project.basedir}/src/main/kotlin</source>
        </sourceDirs>
    </configuration>
</plugin>

And the Kotlin class:

Stateless
open class DummyServiceImpl : DummyService {

    PersistenceContext(unitName = Consts.UNIT_NAME)
    private val em: EntityManager? = null

    override fun get(id: Long?): Dummy {
        return em!!.find<Dummy>(javaClass<Dummy>(), id)
    }

    override fun sayHi(): String {
        return "Dummy service says \"Hi!\"."
    }
}

DummyService and Consts classes are Java classes residing in the same module as DummyServiceImpl. So when I compile the module containing DummyServiceImpl with Maven it goes like this:

[error] C:\somepath\service\DummyServiceImpl.kt: (14, 31) Unresolved reference: DummyService
[error] C:\somepath\service\DummyServiceImpl.kt: (16, 35) Unresolved reference: Consts

If I switch Kotlin plugin execution phase to compile then it predictably fails if there're references from Java to Kotlin classes:

[ERROR] /C:/somepath/service/impl/DummyServiceClientImpl.java:[5,27] cannot find symbol
[ERROR] symbol:   class DummyServiceImpl

So, what's to be done about this? Note that building with IDEA's make goes perfectly fine.

like image 611
arrgh Avatar asked Mar 29 '15 14:03

arrgh


People also ask

Can I use maven for Kotlin?

The kotlin-maven-plugin compiles Kotlin sources and modules. Currently, only Maven v3 is supported.

How do I add a maven project to Kotlin?

Add Kotlin Maven Plugin Now we need to tune this pom file so that it can handle Kotlin sources as well. Then, we need to add the kotlin-maven-plugin to our Maven plugins. We'll configure it to handle both compile and test-compile goals, telling it where to find our sources. This is nearly the end of the configuration.

Can kotlin compile Java?

The Kotlin compiler for JVM compiles Kotlin source files into Java class files. The command-line tools for Kotlin to JVM compilation are kotlinc and kotlinc-jvm . You can also use them for executing Kotlin script files.


4 Answers

Make sure you have this declaration in <build> of your pom.xml

    <plugins>         <plugin>             <groupId>org.jetbrains.kotlin</groupId>             <artifactId>kotlin-maven-plugin</artifactId>             <version>${kotlin.version}</version>             <executions>                 <execution>                     <id>compile</id>                     <phase>process-sources</phase>                     <goals>                         <goal>compile</goal>                     </goals>                     <configuration>                         <sourceDirs>                             <source>src/main/java</source>                             <source>src/main/kotlin</source>                             <source>src/main/resources</source>                         </sourceDirs>                     </configuration>                 </execution>                 <execution>                     <id>test-compile</id>                     <phase>process-test-sources</phase>                     <goals>                         <goal>test-compile</goal>                     </goals>                     <configuration>                         <sourceDirs>                             <source>src/test/java</source>                             <source>src/test/kotlin</source>                             <source>src/test/resources</source>                         </sourceDirs>                     </configuration>                 </execution>             </executions>         </plugin>     </plugins> 

Make sure that all folders (3x in src/main & 3x in src/test) mentioned in the configuration actually exist, even if they don’t contain any classes/resources. You can still fine-tune the configuration once it works for you.

Also pay attention to use exactly the same order I mentioned above to let the compiler compile the Java code first.

like image 143
Alex Avatar answered Sep 21 '22 00:09

Alex


Referred from this Kotlin + java demo apps

You have to execute mvn kotlin:compile before mvn package. mvn kotlin:compile will compile the Kotlin files to class files.

<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/xsd/maven-4.0.0.xsd">     <modelVersion>4.0.0</modelVersion>     <groupId>com.wffweb</groupId>     <artifactId>kotlinminimalproductionsample</artifactId>     <version>0.0.1</version>     <packaging>war</packaging>      <!--     To package as war:- mvn clean kotlin:compile package     -->      <properties>         <maven.build.timestamp.format>yyyyMMddHHmmss</maven.build.timestamp.format>         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>         <maven.compiler.source>1.8</maven.compiler.source>         <maven.compiler.target>1.8</maven.compiler.target>         <kotlin.version>1.2.21</kotlin.version>     </properties>      <dependencies>         <dependency>             <groupId>javax.servlet</groupId>             <artifactId>javax.servlet-api</artifactId>             <version>3.1.0</version>             <scope>provided</scope>         </dependency>         <dependency>             <groupId>javax.websocket</groupId>             <artifactId>javax.websocket-api</artifactId>             <version>1.1</version>             <scope>provided</scope>         </dependency>         <dependency>             <groupId>com.webfirmframework</groupId>             <artifactId>wffweb</artifactId>             <version>RELEASE</version>         </dependency>         <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</artifactId>             <version>${kotlin.version}</version>             <scope>test</scope>         </dependency>     </dependencies>      <build>         <resources>             <resource>                 <directory>src/main/java</directory>                 <includes>                     <include>**/*.properties</include>                 </includes>             </resource>         </resources>         <plugins>             <plugin>                 <groupId>org.codehaus.mojo</groupId>                 <artifactId>exec-maven-plugin</artifactId>                 <version>1.4.0</version>             </plugin>             <plugin>                 <groupId>org.apache.maven.plugins</groupId>                 <artifactId>maven-compiler-plugin</artifactId>                 <version>3.3</version>                 <configuration>                     <source>1.8</source>                     <target>1.8</target>                 </configuration>             </plugin>             <plugin>                 <groupId>org.jetbrains.kotlin</groupId>                 <artifactId>kotlin-maven-plugin</artifactId>                 <version>${kotlin.version}</version>                 <executions>                     <execution>                         <id>compile</id>                         <phase>compile</phase>                         <goals>                             <goal>compile</goal>                         </goals>                     </execution>                     <execution>                         <id>test-compile</id>                         <phase>test-compile</phase>                         <goals>                             <goal>test-compile</goal>                         </goals>                     </execution>                 </executions>                 <configuration>                     <jvmTarget>1.8</jvmTarget>                 </configuration>             </plugin>         </plugins>     </build>  </project> 
like image 37
RRadley Avatar answered Sep 24 '22 00:09

RRadley


I ended using the following configuration to mix Java and Kotlin source code:

<build>
    <sourceDirectory>${project.basedir}/src/main/java</sourceDirectory>
    <testSourceDirectory>${project.basedir}/src/test/java</testSourceDirectory>
    <plugins>
        <plugin>
            <groupId>org.jetbrains.kotlin</groupId>
            <artifactId>kotlin-maven-plugin</artifactId>
            <version>${kotlin.version}</version>
            <executions>
                <execution>
                    <id>compile</id>
                    <phase>compile</phase>
                    <goals>
                        <goal>compile</goal>
                    </goals>
                    <configuration>
                        <sourceDirs>
                            <source>src/main/kotlin</source>
                        </sourceDirs>
                    </configuration>
                </execution>
                <execution>
                    <id>test-compile</id>
                    <phase>test-compile</phase>
                    <goals>
                        <goal>test-compile</goal>
                    </goals>
                    <configuration>
                        <sourceDirs>
                            <source>src/test/kotlin</source>
                        </sourceDirs>
                    </configuration>
                </execution>
            </executions>
        </plugin>
    </plugins>
</build>
like image 41
martin-g Avatar answered Sep 23 '22 00:09

martin-g


Make sure to NOT use the build options: sourceDirectory and testSourceDirectory

pom.xml example

All configurations goes at kotlin-maven-plugin, for more accurate information see: https://kotlinlang.org/docs/maven.html#compile-kotlin-and-java-sources

like image 40
dmonti Avatar answered Sep 22 '22 00:09

dmonti