Kotlin doesn't see Java Lombok accessors?
Asked Answered
B

5

96

Using Kotlin 1.0.0 release (compiling in IntelliJ 15).

println(myPojoInstance.foo)

When it tries to compile code (in IntelliJ or Gradle) that references Lombok based POJOs it gives the error "Cannot access 'foo': it is 'private' in "MyPojo". Which is true, they're all private and my object has @Value @Builder for lombok annotations.

I've tried specifically calling getFoo(), but it says "unresolved reference for getFoo". There's perhaps some trick to make Kotlin aware of how to handle the lombok annotations?

Bromal answered 20/2, 2016 at 0:3 Comment(4)
did you use kapt? blog.jetbrains.com/kotlin/2015/06/…Collywobbles
As @Collywobbles points out, you do not provide enough information about what you have tried to use to resolve this. Also if you tried Kapt, is it within one module or multiple modules.Harrietharriett
I wasn't aware, until "kapt" was mentioned, that there was anything available to try to resolve it. I read the JetBrains page "java-interop" repeatedly and couldn't find anything hinting at how to deal with it. IntelliJ doesn't flag it as an error in the editor, but compiling both in IntelliJ and with Gradle (via JetBrains kotlin gradle plugin) didn't work.Bromal
Did you manage to solve the issue with kapt? I would be interested to know.Leggett
D
95

Generally, no, it doesn't. The reason of that behavior is that Lombok is an annotation processor for javac but when the kotlin compiler runs it uses javac as well but with no annotation processing so this is why kotlin don't see declarations that wasn't yet generated.

The only workaround for now is to define strict compilation order: Java first and after that kotlin. Unfortunately this approach has great disadvantage: you can't use Kotlin code from Java in this case. To workaround it you may need multimodule project that may cause a lot of pain

Danziger answered 20/2, 2016 at 23:8 Comment(5)
Well, darn. Yea, I've taken a chunk of Java in the middle of my program and migrated it to Kotlin specifically to see how Java->Kotlin->Java support will work. The goal being migrating code over time. However, we use Lombok heavily in all of our domain POJOs. Maybe I can hack a "compilePOJOs" target to run before compileJava.Bromal
Sergey, is there JetBrains link/FAQ on how Kotlin looks at co-located Java code (same module)? Gradle does compileKotlin before compileJava, but obviously Kotlin knows about the Java code (aside from annotation preprocessing). Does the Kotlin compiler scan the Java code before compiling the .kt files?Bromal
You are not alone, we have Spring Roo generated POJO and Kotlin doesn't see them as well because of the same reason Sergey told.Prevenient
This is a real showstopper for us as well. We'd like to introduce Kotlin in our apps that rely heavily on lombok Data classes and Builder's. It would be easy to dismiss this as "what did I say about using lombok...", but the fact remains that this will stop many from looking into using Kotlin.Opulent
@Opulent Something that could help is to use DeLombok: projectlombok.org/features/delombok.html to be able to have the Java code generated by Lombok in the source code and then you will be able to remove Lombok from the project.Illusory
C
23

There is a Kotlin compiler plugin for lombok. It is still experimental and it can be used with Gradle or Maven.

It only supports a hand full of annotations, including

  • @Getter, @Setter
  • @NoArgsConstructor, @RequiredArgsConstructor, and @AllArgsConstructor
  • @Data
  • @With
  • @Value

Seem to work as expected. Unfortunately, they do not support the @Builder annotation but you can request to be added in YouTrack

See the Lombok compiler plugin in the kotlin documentation for more information.

Update 1

The @Builder annotation ticket mentioned above has been fixed! The target version for the fix is 1.8.0-Beta.

Cleat answered 31/7, 2021 at 18:5 Comment(0)
I
6

As it was mentioned in comments above, delombok helps. In case of maven build it would be:

<plugin>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok-maven-plugin</artifactId>
    <version>${lombok.version}.0</version>
    <executions>
        <execution>
            <id>delombok</id>
            <phase>generate-sources</phase>
            <goals>
                <goal>delombok</goal>
            </goals>
            <configuration>
                <formatPreferences>
                    <javaLangAsFQN>skip</javaLangAsFQN>
                </formatPreferences>
                <verbose>true</verbose>
            </configuration>
        </execution>
        <execution>
            <id>test-delombok</id>
            <phase>generate-test-sources</phase>
            <goals>
                <goal>testDelombok</goal>
            </goals>
            <configuration>
                <verbose>true</verbose>
            </configuration>
        </execution>
    </executions>
</plugin>
Idell answered 31/5, 2017 at 12:33 Comment(0)
H
6

To add to Sergey Mashkov's response (adding here I don't have enough rep points to comment on it), here's an example app of a Gradle multi-project setup where Kotlin can see the Lombok-generated code (without kapt or delomboking. Caveats do apply - namely, Kotlin can call the Java code, but Java can't call the Kotlin code in that particular module (as this would create a circular dependency). This kind of build might be suitable if you have an existing Java codebase and all new code is written in Kotlin, though.

I would love to see full Lombok/Kotlin support, however. While Kotlin is fully interoperable with Java, the reality is that Lombok is very widely used, and this issue may prevent a large number of developers who would like to switch to Kotlin from doing so.

Hyderabad answered 24/1, 2018 at 18:33 Comment(0)
H
4

Looks like it works if you use delombok according to site and add the target/generated-sources/delombok folder in the pom.xml under build > plugins > plugin > kotlin-maven-plugin

Hemotherapy answered 28/4, 2018 at 8:20 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.