Search code examples
javamavenintellij-ideakotlinvaadin

Mixing Java and Kotlin with Maven, can't find symbol


I'm trying to add some Kotlin classes into my existing Java project under Vaadin Framework (v 8.4.5).

I've fully read the tutorial on how to mixing java and Kotlin, and I've successfully created a Kotlin class inside my existing Java Project.

The new Kotlin class is inside my project (ofc I've cutted away all code for privacy)

package it.projectName.utils

import it.projectName.otherClasses

class SecurityUtils (user: User) {
    //various val and var, and of course the isCrypted calculated val

    init {
        if(!isCrypted){
            //encrypt user password
        }
    }
}

Now I'm using this Kotlin class inside my Java class with

import it.projectName.utils.SecurityUtils;
public class UserDao{
    //[... other code ...]
    SecurityUtils securityUtils = new SecurityUtils(user);
}

Everything is fine, I don't get any compiler error. But when I try to run my project with maven with jetty:run , it throws an error:

[ERROR] COMPILATION ERROR : 
[INFO] -------------------------------------------------------------
[ERROR] /C:/pathToClass/UserDao.java:[9,36] cannot find symbol
  symbol:   class SecurityUtils
  location: package it.projectName.utils
[INFO] 1 error
[INFO] -------------------------------------------------------------

The line he's referring to is import it.projectName.utils.SecurityUtils;

I've checked my pom.xml, everything looks fine there aswell:

    <properties>
        <kotlin.version>1.2.61</kotlin.version>
        <kotlin.compiler.incremental>true</kotlin.compiler.incremental>
    </properties>

    <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>

    <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>
                            <sourceDir>src/main/java</sourceDir>
                            <sourceDir>src/main/kotlin</sourceDir>
                        </sourceDirs>
                    </configuration>
                </execution>
                <execution>
                    <id>test-compile</id>
                    <phase>test-compile</phase>
                    <goals>
                        <goal>test-compile</goal>
                    </goals>
                    <configuration>
                        <sourceDirs>
                            <sourceDir>src/main/java</sourceDir>
                            <sourceDir>src/main/kotlin</sourceDir>
                        </sourceDirs>
                    </configuration>
                </execution>
            </executions>
            <configuration>
                <jvmTarget>1.8</jvmTarget>
            </configuration>
        </plugin>

What I'm missing? Thanks


Solution

  • We have to use two different source directories for each, under the src/main directory. (I'm talking about maven folder structure).

    For example for Java, it is src/main/java and for Kotlin, it's like src/main/kotlin.

    As per the documentation here, under topic of Compiling Kotlin and Java sources, JetBrains provides comprehensive maven plugin to declare each of aforementioned directories as their corresponding source directory. So then the compiler can detect both source directories, and in the building process, able to copy respective binary files to the class path.

    Here is that maven plugin declaration,

    <build>
    <plugins>
        <plugin>
            <artifactId>kotlin-maven-plugin</artifactId>
            <groupId>org.jetbrains.kotlin</groupId>
            <version>${kotlin.version}</version>
            <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>3.5.1</version>
            <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>
    

    Also, I personally recommend following property must be there to increase the speed of build process.

    <properties>
        <kotlin.compiler.incremental>true</kotlin.compiler.incremental>
    </properties>
    

    This one had worked for me pretty well, even if you creating a maven project with modules.