I'm looking for a way to write a Kotlin data class that compiles the annotations to the same bytecode as the following Java class:
public class Pet {
private List<String> names;
public @NonNull List<@NonNull String> getNames() {
return names;
}
// constructor, setter, etc. omitted
}
I tried to write the following data class and expected it to put the annotations on the getter's return type and return type parameter:
data class Pet(val names: @get:NonNull List<@get:NonNull String>)
But for each of the annotations I get two compile errors:
- This annotation is not applicable to target 'undefined target' and use site target '@get'
- This annotation is not applicable to target 'type usage' and use site target '@get'
The NonNull annotation is from the Java library microprofile-graphql-api:
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE_USE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER})
@Documented
public @interface NonNull {
}
I run into the same problem when I try to set the annotations on the field:
data class Pet(val names: @field:NonNull List<@field:NonNull String>)
If I remove the use-site targets, then it will compile but it will only compile the annotations into @kotlin.Metadata where they are not visible to a Java library that is not aware of Kotlin.
Is there a way to get the annotations on the type and type parameter of a getter method or field?
Update
The getNames() method in the Java snippet above compiles to
public getNames()Ljava/util/List;
@Lorg/eclipse/microprofile/graphql/NonNull;()
@Lorg/eclipse/microprofile/graphql/NonNull;() : METHOD_RETURN, null
@Lorg/eclipse/microprofile/graphql/NonNull;() : METHOD_RETURN, 0;
The first annotation is on the method, the second on the method return type (List) and the third on the method return type parameter (String). I'm looking for a solution that results in bytecode with at least the second and third annotations.
The proposed solutions so far and what they compile to
1.
data class Pet(@NonNull val names: List<@NonNull String>)
public getNames()Ljava/util/List;
This solution does not contain any annotations on the getter method at all in the bytecode. The annotations are only compiled into @kotlin.Metadata where they are not visible to a Java library that is not aware of Kotlin.
2.
data class Pet(@get:NonNull val names: List<@NonNull String>)
public final getNames()Ljava/util/List;
@Lorg/eclipse/microprofile/graphql/NonNull;()
This solution only results in an annotation on the method, but not on the method return type or return type parameter.