Transitive dependencies from an annotation-processor

TLDR; Is there a way to provide transitive compile dependencies from a dependency defined as an annotationProcessor?

I maintain an annotation processor which performs JPA static metamodel generation. Part of that generation is the need to add the annotation @jakarta.annotation.Generated from the jakarta.annotation:jakarta.annotation-api library.

For example, given a JPA entity like:

@Entity
class SomeEntity { ... }

the generator will produce:

@jakarta.annotation.Generated
class SomeEntity_ { ... }

To achieve this, a project would have:

dependencies {
    ...
    annotationProcessor "org.hibernate.orm:hibernate-jpamodelgen"
}

At the moment, the static metamodel class (SomeEntity_) is generated fine, but it fails to compile because jakarta.annotation.Generated cannot be found. The only way I have found so far to have this work “properly” is to add the jakarta.annotation:jakarta.annotation-api dependency directly on the project:

dependencies {
    ...
    compileOnly "jakarta.annotation:jakarta.annotation-api"
    annotationProcessor "org.hibernate.orm:hibernate-jpamodelgen"
}

To me this seems like unnecessary duplication. The use of org.hibernate.orm:hibernate-jpamodelgen will always imply the need for jakarta.annotation:jakarta.annotation-api as a compile dependency, but as far as I can tell there is no way to achieve this.

Is there?

P.S. I saw reference to possibly needing to explicitly define the annotationProcessor Configuration as transitive. I have no idea if it is or not by default, but explicitly defining it so had no effect.

I don’t think there is a way.

The annotation classpath is intentionally separated from the compile classpath.
That you need a jar as it contains the annotation processor, and that you need the dependencies it declares so that the annotation processor can run, does in no way mean that any of those classes is necessary for compiling the result.
The result does not even have to be a source file.

The annotationProcessor configuration of course is transitive, otherwise annotation processors could not have dependencies they need to run.

If a project decides so, it could for example make the compileOnly configuration extend the annotationProcessor configuration and thus inherit all declared dependencies. But imho this is often not the best idea. Maybe the annotation processor generated sources have even runtime dependencies, …

So imho it is indeed the correct way to declare the annotation processor for the annotationProcessor configuration, any compile-time only dependencies the generated sources have as compileOnly if there are any, any runtime only dependencies as runtimeOnly, any compile-time dependencies that are part of the api as api dependencies and any compile-time dependencies that are only part of the implementation as implementation dependencies.

If the annotation processor’s result has various such dependencies and maybe even for various of those configurations, it could maybe make sense to provide a Gradle plugin that adds those dependencies to the according configurations. If it is just that one annotations dependency it might not be worth the effort and the users should just define the dependency explicitly.

Thanks as always!

I get what you are saying as a general rule. But IMO this illustrates a situation where it leads to unnecessary verbosity.

Oh well…

Feel free to open some feature request. :slight_smile: It would probably need some Gradle specific metadata that is embedded inside the annotation processor that could then define what I said the plugin could do. But even if considered, it will probably not be too high prio except maybe if you contribute the feature. :slight_smile:

In the larger ecosystem its not worthwhile I think. I even stated that :wink:

This is just an exception to the rule where it leads to extra verbosity.

I’m not sure I agree. :slight_smile:

Yours is for sure not the only annotation processor where the generated sources need some dependencies.
And it would also not be the first Gradle-specific code within annotation processors, as annotation processors can opt-in in a Gradle-specific way to incremental annotation processing.

Voila - Allow an annotation processor to indicate dependencies for transitivity · Issue #25187 · gradle/gradle · GitHub

1 Like