Lombok and Gradle/Kotlin: Didn't find documentation, made it work anyway!

In "Spring in Action", 6th edition, example code is compiled using Maven (and any of several IDEs), but I wanted to use Gradle/Kotlin.

Example code uses Lombok ( https://projectlombok.org/ ) to generate those tedious-to-write constructors and accessors.

(The description for Lombok at https://objectcomputing.com/resources/publications/sett/january-2010-reducing-boilerplate-code-with-project-lombok is a bit out of date.)

Example:

package tacos;

import lombok.Data;

@Data
public class Ingredient {
private final String id;
private final String name;
private final Type type;
public enum Type { WRAP, PROTEIN, VEGGIES, CHEESE, SAUCE }
}

For the above, all getters and the required 3-arg constructor are generated on-the-fly by Lombok which is triggered the @Data annotation (must be modification of the Abstract Syntax Tree during the compilation phase, very sly).

If we now run a test:

package tacos;

import org.junit.jupiter.api.Test;

public class TacoTests {

@Test
void buildTacoIngredient() {
// call the all-arg constructor that lombok generated
Ingredient i1 = new Ingredient("id","name", Ingredient.Type.CHEESE);
}
}

... the compiler complains: "error: package lombok does not exist" and "cannot resolve symbol Data"

This can be temporarily fixed by using the suggestion "add lombok to classpath" which adds the following to the dependencies in build.gradle.kts (I somehow managed to add the dependency several times via different error messages, IDEA doesn't check whether the dependency has already been included it seems):

dependencies {
...
implementation
("org.projectlombok:lombok:1.18.26")
...
}

Evidently the test still does not run because lombok doesn't do its magic at compile time. When running the test we now get:

error: variable id not initialized in the default constructor
    private final String id;
^

Indeed, the all-arg constructor for Ingredient cannot be found yet.

Although there is a Gradle plugin for Lombok: https://plugins.gradle.org/plugin/io.freefair.lombok I could do without.

The dependencies have to be modified as follows: Remove the implementation line added by IDEA and add these:

val lombok_version = "1.18.26"

dependencies
{
...
compileOnly("org.projectlombok:lombok:" + lombok_version)
annotationProcessor("org.projectlombok:lombok:" + lombok_version)
testCompileOnly("org.projectlombok:lombok:" + lombok_version)
testAnnotationProcessor("org.projectlombok:lombok:" + lombok_version)
...
}

Additionally, to see what annotation processors are being used during compilation

tasks.withType<JavaCompile> {
doFirst {
println("AnnotationProcessorPath for '$name' is ${options.annotationProcessorPath?.joinToString(prefix = "\n", separator = "\n", transform = { it -> it.toString() })}")
}
}

The complete dependencies with Spring, Spring Boot, Spring Dev Tools and the JetBrains annotation support for @NotNull is given by by the following. I have no from where the DependencyHandler developmentOnly comes from, in principle it should be declared but apparently that's not needed here (the list of predefined handlers is at  https://docs.gradle.org/current/userguide/java_plugin.html#tab:configurations )

dependencies {
implementation("org.springframework.boot:spring-boot-starter-thymeleaf")
implementation("org.springframework.boot:spring-boot-starter-web")
implementation("org.jetbrains:annotations:24.0.0")

compileOnly("org.projectlombok:lombok:" + lombok_version)
annotationProcessor("org.projectlombok:lombok:" + lombok_version)

testCompileOnly("org.projectlombok:lombok:" + lombok_version)
testAnnotationProcessor("org.projectlombok:lombok:" + lombok_version)

developmentOnly("org.springframework.boot:spring-boot-devtools")
testImplementation("org.springframework.boot:spring-boot-starter-test")
}

Now relaod the Gradle script, run the Gradle test "clean" via the Gradle sidebar

and then run the JUnit test again:

> Task :compileJava
AnnotationProcessorPath for 'compileJava' is 
/home/aloy/.gradle/caches/modules-2/files-2.1/org.projectlombok/lombok/1.18.26/8f8cf0372abf564913e9796623aac4c8ea44025a/lombok-1.18.26.jar
> Task :processResources
> Task :classes
> Task :compileTestJava
AnnotationProcessorPath for 'compileTestJava' is 
/home/aloy/.gradle/caches/modules-2/files-2.1/org.projectlombok/lombok/1.18.26/8f8cf0372abf564913e9796623aac4c8ea44025a/lombok-1.18.26.jar
> Task :processTestResources NO-SOURCE
> Task :testClasses
> Task :test
BUILD SUCCESSFUL in 930ms
4 actionable tasks: 4 executed
14:58:56: Execution finished ':test --tests "tacos.TacoTests.buildTacoIngredient"'.

Looks like it works!

 

 

0

Please sign in to leave a comment.