I have an annotation that can be added on METHOD and TYPE and is used in thousands of places in our project.
@Retention(java.lang.annotation.RetentionPolicy.RUNTIME)
@Target({METHOD, TYPE})
@Inherited
public @interface RequiredStore{
Store value();
}
Is it possible to make the annotation deprecated only on methods while keeping it non-deprecated on types? I want other developers to be notified by IDE that it should not be used on methods any more, until we'll refactor all existing usages and finally remove the METHOD part.
If it's not possible, is there any Way to handle such case beside creating new annotation only for types and deprecating the old one?
You could use an annotation Processor.
For example, the annotation and its processor would be placed in its own .jar file and added as a dependency of the sources that use the annotation.
The custom .jar would have the following structure:
src/main/
java/com/company/annotations/
RequiredStore.java
RequiredStoreProcessor.java
resources/META-INF/services
javax.annotation.processing.Processor
RequiredStore.java stays as you have it above.
RequiredStoreProcessor.java could look something like this:
package com.company.annotations;
import java.util.Set;
import javax.annotation.processing.AbstractProcessor;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
import javax.lang.model.element.ElementKind;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic;
@SupportedAnnotationTypes("com.company.annotations.RequiredStore")
public class RequiredStoreProcessor extends AbstractProcessor {
@Override
public boolean process(
Set<? extends TypeElement> annotations,
RoundEnvironment roundEnv) {
for (Element element
: roundEnv.getElementsAnnotatedWith(RequiredStore.class)) {
if (element.getKind().equals(ElementKind.METHOD)) {
processingEnv.getMessager().printMessage(
Diagnostic.Kind.WARNING,
"Using @RequiredStore on methods has been deprecated\n"
+ "Class: " + element.getEnclosingElement() + "\n"
+ "Method: " + element.getSimpleName() + "\n");
}
}
// Other processing...
return false;
}
@Override
public SourceVersion getSupportedSourceVersion() {
return SourceVersion.latest();
}
}
The javax.annotation.processing.Processor file allows javac to pickup the Processor via SPI and simply contains
com.company.annotations.RequiredStoreProcessor
Finally, compile this into a .jar and add it to the classpath where the annotations are being used. Any methods that have the @RequiredStore will produce a compiler warning. For example, for this class,
package com.company.business;
import com.company.annotations.RequiredStore;
@RequiredStore
public interface Business {
@RequiredStore
public void someMethod();
}
The compiler warning would be this:
warning: Using @RequiredStore on methods has been deprecated Class: com.company.business.Business Method: someMethod
As for an indication in the IDE, you might have to write a custom inspection and unfortunately this depends on the IDE used.
Decent custom annotations reference: Code Generation using Annotation Processors in the Java language
If you are okay about using native aspectj, another option is to use AspectJ's code enforcement policy this way:
public aspect RequiredStoreAnnotationCheck {
declare warning: execution(@RequiredStore * *.*(..)) : "Required store annotation not appropriate for methods..";
}
If the IDE is integrated with AspectJ, this would be flagged as a compile time check.
AspectJ in action book has a good amount of detail on this too.
Here is one of my blog articles for more context: http://www.java-allandsundry.com/2012/03/code-policy-enforcement-using-aspectj.html
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With