Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mixed Kotlin + Java with Maven, unresolved reference

I have a Maven project with Kotlin code hello.kt which calls Java code JavaFoo.java which calls Kotlin code KotlinFoo.kt. hello.kt also calls KotlinFoo.kt directly. I'm trying to build this with mvn clean install using exactly the Maven settings described in kotlinlang's Maven docs.

If hello.kt doesn't call JavaFoo (but I leave JavaFoo in the project) then this builds just fine.

The docs say that the Kotlin compiler should be invoked before the Java compiler, which suggests to me that all Kotlin code needs to compile before any Java code, i.e. with this setup you can call Kotlin from Java but not vice versa. However, the docs describe this setup as just "mixed code applications", not "calling Kotlin from Java".

In other words, this failure seems consistent with what the docs seem to imply but not with what they directly say -- or I'm just misunderstanding something.

I want to call each language from the other. Is there a Maven configuration that will do this, please?

(I looked at various StackExchange questions on mixed code settings and none of the solutions works for me.)

Adding the code as requested: pom.xml:

<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.kotlindemo</groupId>
    <artifactId>kotlin-demo</artifactId>
    <packaging>jar</packaging>
    <version>1.0-SNAPSHOT</version>
    <name>kotlin-demo</name>

    <properties>
        <kotlin.version>1.1.2-2</kotlin.version> 
        <kotlin.compiler.incremental>true</kotlin.compiler.incremental>
        <main.class>com.example.kotlindemo.HelloKt</main.class>
    </properties>

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

    <build>
        <plugins>
            <plugin>
                <artifactId>kotlin-maven-plugin</artifactId>
                <groupId>org.jetbrains.kotlin</groupId>
                <version>${kotlin.version}</version>
                <executions>
                    <execution>
                        <id>compile</id>
                        <phase>process-sources</phase>
                        <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>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-assembly-plugin</artifactId>
                <version>2.6</version>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals> <goal>single</goal> </goals>
                        <configuration>
                            <archive>
                                <manifest>
                                    <mainClass>${main.class}</mainClass>
                                </manifest>
                            </archive>
                            <descriptorRefs>
                                <descriptorRef>jar-with-dependencies</descriptorRef>
                            </descriptorRefs>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

src/main/kotlin/hello.kt:

package com.example.kotlindemo

fun main(args : Array<String>) { 
  println("Hello, world!") 

  var kfoo = KotlinFoo()
  kfoo.printFooString()

  kfoo.fooString = "init2"
  kfoo.printFooString()

  var foo2 = JavaFoo("abcd")
  foo2.printString()
}

src/main/kotlin/KotlinFoo.kt:

package com.example.kotlindemo

class KotlinFoo {
    var fooString = "init"

    fun printFooString() {
        println(this.fooString) 
    }
}

src/main/java/JavaFoo.java:

package com.example.kotlindemo;

class JavaFoo {
    private KotlinFoo k;

    JavaFoo(String initializer) {
        k = new KotlinFoo();
        k.setFooString(initializer);
    }

    void printString() {
        this.k.printFooString();
    }
}

Error:

[ERROR] .../src/main/kotlin/hello.kt: (12, 14) Unresolved reference: JavaFoo
like image 431
user747267 Avatar asked May 18 '17 16:05

user747267


People also ask

How do I fix Kotlin unresolved reference?

Please make sure that you add the id 'kotlin-android-extensions' line on the build. gradle file that's inside your app module. Once you sync the Gradle build, the error should disappear.

Can you use Kotlin with Maven?

If you still prefer to stick with good old Maven, there is no problem. There is a plugin for it to support Kotlin as well. If you don't have Maven on your machine, you can follow the instructions at https://maven.apache.org/install.html to get it installed on your local machine.

What does Kotlin Maven plugin do?

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


1 Answers

The compilation fails because your Java class is not in a directory that matches its package statement. While Kotlin allows you to put classes in any directories regardless of the package they're in, Java requires you to put each file in a package that corresponds to its directory. This requirement applies to mixed-language projects as well.

To fix the error, move JavaFoo.java to src/main/java/com/example/kotlindemo.

like image 89
yole Avatar answered Sep 30 '22 10:09

yole