How to extend Java annotation?

JavaAnnotations

Java Problem Overview


In my project I use pre-defined annotation @With:

@With(Secure.class)
public class Test { //....

The source code of @With:

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface With { 

    Class<?>[] value() default {};
}

I want to write custom annotation @Secure, which will have the same effect as @With(Secure.class). How to do that?


What if I do like this? Will it work?

@With(Secure.class)
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Secure {

}

Java Solutions


Solution 1 - Java

As piotrek pointed out, you cannot extend Annotations in the sense of inheritance. Still, you can create Annotations that aggregate others:

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface SuperAnnotation {
    String value();
}

@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface SubAnnotation {
    SuperAnnotation superAnnotation();
    String subValue();
}

Usage:

@SubAnnotation(subValue = "...", superAnnotation = @SuperAnnotation(value = "superValue"))
class someClass { ... }

Solution 2 - Java

From Java language specification, Chapter 9.6 Annotation Types:

> No extends clause is permitted. (Annotation types implicitly extend annotation.Annotation.)

So, you can not extend an Annotation. you need to use some other mechanism or create a code that recognize and process your own annotation. Spring allows you to group other Spring's annotation in your own custom annotations. but still, no extending.

Solution 3 - Java

To expand on Muhammad Abdurrahman's answer--

@With(Secure.class)
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Secure {

}

This does not work by default but you can use it in conjunction with Spring's AnnotationUtils.

See this SO answer for an example.

Solution 4 - Java

@With(Secure.class)
@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
public @interface Secure {

}

This will work.

Solution 5 - Java

You can use annotation for annotation like this:

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@WithSecurityContext(factory = WithCustomUserSecurityContextFactory.class)
public @interface WithCustomUser {
  String username() default "demo@demo.com";
  String password() default "demo";
  String[] authorities() default {Authority.USER};
}

And define exact state in its "child"

@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
@WithCustomUser(username = "[email protected]",
                password = "admin",
                authorities = {Authority.USER, Authority.ADMINISTRATOR})
public @interface WithAdminUser {
}

In this case you have a some kind of "state" and access to the parent annotation fields via reflection/aspect.

Solution 6 - Java

So the provided answer from Eric Jiang is 100% working in my situation and she is: I need JMSListener ,but i want to hide the destination name:

@GetPlayerDataByUUIDListener
    public void getPlayerDataByUUID(Object message) {
        System.out.println("Im Here");
    }

`

@JmsListener(destination = PlayerStatisticsJMSConstants.GET_PLAYER_DATA_BY_UUID)
@Target({ElementType.METHOD})
@Retention(RetentionPolicy.RUNTIME)
public @interface GetPlayerDataByUUIDListener {
}

So this is working perfectly ,and it is the same as:

@JmsListener(destination = "example")
    @GetPlayerDataByUUIDListener
    public void getPlayerDataByUUID(Object message) {
        System.out.println("Im Here");
    }

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionbvitaliygView Question on Stackoverflow
Solution 1 - JavaHalmackenreuterView Answer on Stackoverflow
Solution 2 - JavapiotrekView Answer on Stackoverflow
Solution 3 - JavaEric JiangView Answer on Stackoverflow
Solution 4 - JavaMuhammad AbdurrahmanView Answer on Stackoverflow
Solution 5 - Javauser2210419View Answer on Stackoverflow
Solution 6 - JavaGeorgi PeevView Answer on Stackoverflow