0

I am new to the concept of Java annotation. I would like to write a Java annotation as follows for my Spring boot application:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
public @interface MyAnnotation {
      
  DataType type() default null;

  Class<? extends DataProcessor> dataProcessor() <--I WOULD LIKE TO ADD ONE CLASS LITERAL IMPLEMENTING DATAPROCESSOR INTERFACE DEFINED BELOW


      default NullDataProcessor.class;

}

Interface DataProcessor is defined as below:

public interface DataProcessor {
  String process(DataType type, Map<String, Object> input);
}

The above annotation I would like to use for a method, something like below:

@MyAnnotation(dataProcessor=MyDataProcessorImpl.class)

So here I have three questions:

  1. How exactly I will add a class literal as a member of Java annotation?
  2. How will I define multiple implementations of the interface?
  3. How will I define default implementation i.e. NullDataProcessor?

Could anyone please help here? Thanks.

EDIT

  1. From Pass method argument in Aspect of custom annotation, I got an idea regarding how to extract a value from method params with the help of an aspect. But I cannot understand, how to invoke the function: process() for the method params.
Joy
  • 4,197
  • 14
  • 61
  • 131

1 Answers1

2
  1. You've already done so:

    @MyAnnotation(dataProcessor=MyDataProcessorImpl.class)
    
  2. Make the annotation element an array:

    @Retention(RUNTIME)
    @Target(METHOD)
    public @interface MyAnnotaiton {
        Class<? extends DataProcessor>[] dataProcessors();
    }
    

    Or make the annotation repeatable:

    @Retention(RUNTIME)
    @Target(METHOD)
    @Repeatable(MyAnnotations.class)
    public @interface MyAnnotation {
       Class<? extends DataProcessor> dataProcessor();
    }
    
    @Retention(RUNTIME)
    @Target(METHOD)
    public @interface MyAnnotations {
        MyAnnotation[] value();
    }
    
  3. Add a default value to the annotation element:

    @Retention(RUNTIME)
    @Target(METHOD)
    public @interface MyAnnotation {
        Class<? extends DataProcessor> dataProcessor() default NullDataProcessor.class;
    }
    

    If you use an array it may be better to leave the default value as an empty array and simply have the code that processes the annotation handle that special case.

Slaw
  • 37,820
  • 8
  • 53
  • 80
  • thanks for your answer. One small doubt. Regarding the default class i,e, NullDataProcessor, should I add an implementation for the same, like having a blank method for process()? – Joy Jul 25 '21 at 15:17
  • 1
    I assumed you'd defined a `public class NullDataProcessor implements DataProcessor { ... }` implementation. You can't have a class literal to a class that does not exist at compile time. – Slaw Jul 25 '21 at 15:18
  • I am not able to understand how to call the function defined in the annotation class on the method arguments as I mentioned OP. Could you please help with this? Thanks. – Joy Jul 26 '21 at 01:41
  • In plain Java that would involve querying the annotation for the class type, instantiating the class (probably via reflection), and then invoking the method. But as you seem to want to integrate with Spring I'm not sure I can be of much help—I'm not familiar with Spring. – Slaw Jul 26 '21 at 02:44
  • sure, no problem. If possible, could you please provide a small code snippet in order to do the same in plain java? – Joy Jul 26 '21 at 03:02
  • I assume you get the `DataType` argument from the annotation as well? Where do you get the `Map` argument? – Slaw Jul 26 '21 at 10:34