Gradle plugin and Java annotation that checks (and fails the build if there are missing annotations) class fields for the annotations.
The main story of this plugin and the annotation started with the missing SerializedName
annotations for network model classes. Because of the missing SerializedName
annotation in the network model classes, our JSON serialization/deserialization operations were failing.
It is a developer mistake to forget some required annotation but this mistake can be avoidable with this annotation and the plugin.
To use the annotation:
- Add maven central repository
mavenCentral()
. - Add dependency as an implementation and annotation processor:
implementation "eu.bolt:requiresannotation.annotation:1.2"
annotationProcessor "eu.bolt:requiresannotation.processor:1.2"
// lets declare both annotationProcessor and kapt of them https://issuetracker.google.com/issues/80270236
kapt "eu.bolt:requiresannotation.processor:1.2"
You can use @RequiresAnnotation
for the methods and the classes. For classes, it will also search for the required annotation in the defined method's parameters.
@RequiresAnnotation(requires = [ANNOTATION_CLASS_ARRAY], ignore = [CLASS_ARRAY])
- requires: Annotations that at least one of them is required in the parameters of this class' methods.
- ignore: Ignore the classes for required annotation checks.
Let's assume that we have a class and we want every method parameter in this class should be non-null and should be annotated with @NonNull
annotation
public class SomeClass {
public void someStringMethod(String stringParam){}
public void someIntegerMethod(@NonNull Integer integerParam){}
public void someCustomClassMethod(MyClass integerParam){}
}
In this case someStringMethod
's stringParam
don't have @NonNull
annotation. But on the other hand, inside this class we only accept someCustomClassMethod
's MyClass
parameter as a null. For informing the developer about missing annotation, we can fail the build using this annotation with following configruation:
@RequiresAnnotation(requires = [NonNull.class], ignore = [MyClass.class])
and we can place this annotation on the class. So the last version of the class will look like:
@RequiresAnnotation(requires = [NonNull.class], ignore = [MyClass.class])
public class SomeClass {
public void someStringMethod(String stringParam){}
public void someIntegerMethod(@NonNull Integer integerParam){}
public void someCustomClassMethod(MyClass integerParam){}
}
When we start the build, it will be failed because of the someStringMethod
and it will ignore the someCustomClassMethod
because of the ignored MyClass
.
The plugin of the annotation allows you to use other annotations also for the check. To use the plugin, you must first apply it and then configure the parameter described below. To apply the plugin in the
- Add maven central repository
mavenCentral()
to thebuildscript
in the root project'sbuild.gradle
- Add dependency
classpath "eu.bolt:requiresannotation.plugin:1.2"
to thebuildscript
in the root project'sbuild.gradle
buildscript {
repositories {
mavenCentral()
}
dependencies {
classpath "eu.bolt:requiresannotation.plugin:1.2"
}
}
- Apply plugin
apply plugin: 'requiresannotation.plugin'
to module in the module'sbuild.gradle
You can configure Requires Annotation using this plugin from module's build.gradle
file. With the configuration, the annotation processor can also process the other annotations.
requiresAnnotationProcessor {
requires = ['TARGET_ANNOTATION_PACKAGE_NAME': ['REQUIRED_ANNOTATION_PACKAGE_NAMES']]
ignore = ['IGNORED_PACKAGE_NAMES']
}
Let's assume that we are using Retrofit
library for the API calls.
@POST("/driverPhoneDetails")
Single<ServerResponse> sendSomeRequest(@Body SomeRequestModel body);
We want to fail the build if some of the fields in the SomeRequestModel
class don't have SerializedName
annotation.
data class SomeRequestModel(
@SerializedName("string_field")
val stringField: String,
val intField: Int)
If we make an API call with this model, most probably it will fail on the release build because of the obfuscation causes the field name changes and the JSON serialization/deserialization library uses field names if JSON property name not given using the SerializedName
annotation. In this case, there is a missing SerializedName
annotation on the intField
field.
So we need to check all the class fields used in the methods annotated with @POST
for the @SerializedName
annotation. Requires Annotation can do this check with the following configuration on the module's build.gradle
file:
requiresAnnotationProcessor {
requires = ['retrofit2.http.POST': ['com.google.gson.annotations.SerializedName']]
ignore = ['com.example.MyIgnoreClass']
}