Incremental Groovy compilation with annotation processor in Java

Hi, I’m struggling to find the way to make Groovy incremental compilation work when I use annotation processors in Java.

I’ve created a dummy project where I use 3 source sets: main, test and componentTest. In main, I have a single Java class annotated with Lombok. In test, I have a single Groovy test class that instantiates the class written in Java.

I’ve setup this dummy project so that I can find a fix for a bigger one where I’m facing the same issue.

When I enable Groovy incremental compilation and build the project, I get an error that says:

Enabling incremental compilation and configuring Java annotation processors for Groovy compilation is not allowed. Disable incremental Groovy compilation or remove the Java annotation processor configuration.

This is expected since a change made to Gradle last year: https://github.com/gradle/gradle/issues/9871

I’d like to know whether it’s possible to enable Groovy incremental compilation somehow if I use any annotation processor in a different source set in Java.

Versions:
Gradle: 6.6.1
Lombok: 1.18.16 (through io.freefair.lombok plugin 5.3.0)
Groovy: 3.0.7
Java: 11

build.gradle

plugins {
	id 'org.springframework.boot' version '2.4.0'
	id 'io.spring.dependency-management' version '1.0.10.RELEASE'
	id 'java'
	id 'groovy'
	id "io.freefair.lombok" version "5.3.0"
}

group = 'com.example'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'

repositories {
	mavenCentral()
}

configurations {
	componentTestImplementation.extendsFrom testImplementation
}

tasks.withType(GroovyCompile).configureEach {
	options.incremental = true
}

dependencies {
	implementation 'org.springframework.boot:spring-boot-starter'

	testImplementation 'org.springframework.boot:spring-boot-starter-test'
	testImplementation 'org.spockframework:spock-spring:2.0-M4-groovy-3.0'
	implementation group: 'org.codehaus.groovy', name: 'groovy', version: '3.0.7'

	componentTestImplementation 'org.springframework.boot:spring-boot-starter-test'
	componentTestImplementation 'io.cucumber:cucumber-spring:6.9.0'

	componentTestImplementation platform('org.testcontainers:testcontainers-bom:1.15.0') //import bom
	componentTestImplementation('org.testcontainers:postgresql') //no vers
}

sourceSets {
	componentTest {
		java {
			compileClasspath += main.output + test.output
			runtimeClasspath += main.output + test.output
			srcDir file('src/componentTest/java')
		}
		resources.srcDir file('src/componentTest/resources')
	}
}

task componentTest(type: Test) {
	testClassesDirs = sourceSets.componentTest.output.classesDirs
	classpath = sourceSets.componentTest.runtimeClasspath
}

check.dependsOn componentTest
componentTest.mustRunAfter test

test {
	useJUnitPlatform()
}

componentTest {
	useJUnitPlatform()
}

settings.gradle

rootProject.name = 'tdd-playground'

enableFeaturePreview('GROOVY_COMPILATION_AVOIDANCE')

Account.java

package com.example.tddplayground;

import lombok.Value;

import java.math.BigDecimal;

@Value
public class Account {

    String name;
    BigDecimal amount;
}

AccountTest.groovy

package com.example.tddplayground

import spock.lang.Specification

class AccountTest extends Specification {

    def "test"() {
        when:
        def accountId = new Account("Main account", BigDecimal.ZERO)

        then:
        accountId.name == "Main account"
        accountId.amount == BigDecimal.ZERO
    }
}

@Stefan_Wolf posting the question here since I believe it’s more appropriate.

I don’t understand what I need to do when you say:

@albloptor I the Lombok annotation processor configured for the Groovy compilation as well? If it isn’t (and it shouldn’t be), then I think incremental Groovy compilation should work if you enabled it.

Thanks in advance!

Hi Alberto,

IIUC, you don’t want to use the annotation processor in your Groovy source set. Since Gradle detects that you have annotation processing enabled for Groovy compilation, that means that the Lombok annotation processor ended up on the options.annotationProcessorPath. I suppose the io.freefair.lombok plugin adds it there. In order to disable annotation processing, can add -proc:none to options.comilerArgs or clear the `annotationProcessorPath.

Hope that helps,
Stefan

Hi Stefan,

I finally made it work thanks to your response.

It turns out the Lombok plugin inserts the annotationProcessor and compileOnly into each source set in the project, which means Java annotation processing was actually enabled with Groovy.

What I did to fix this was to stop using the plugin altogether and use compileOnly and annotationProcessor for main and nothing for test. So no testCompileOnly or testAnnotationProcessor.

Now both my Java and Groovy code are happily compiling incrementally whenever I update any class.

This was actually a toy project to help me find a solution for a similar problem in a big project at work. While that one won’t be as easy to fix becuase it’s a lot more complex and messier, at least now I understand what the underlying issue is.

Thank you very much for your help, I really appreciate it!