DEV Community

André Laugks
André Laugks

Posted on • Edited on

Using nested annotations for key-value pairs in a custom annotation

Introduction

In my article "Using a hashmap in a custom annotation" I explained how to use a HashMap in an annotation using an Enum Constant.

Annotations are allowed as type in an annotation. This means that nested annotations can be used to define key-value pairs in a custom annotation.

List of supported Types in Annotations

Annotations

Two customs annotations are required. The first annotation (e.g. MapItem) containing a key-value pair and the second annotation (e.g. MapItems) containing a list of MapItem annotations.

Custom Annotation @MapItem

The annotation @MapItem represents a single key-value pair.

@Target(ElementType.FIELD)
public @interface MapItem {

    String key();
    String value();
}
Enter fullscreen mode Exit fullscreen mode

Custom Annotation @MapItems

The annotation @MapItems defines a list of MapItem.

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface MapItems {

    MapItem[] items();
}
Enter fullscreen mode Exit fullscreen mode

Functional Test

The list of @MapItem annotations are set in the @MapItems annotation.

class ExampleDto {

    @MapItems(items = {
        @MapItem(key = "1", value = "MALE"),
        @MapItem(key = "2", value = "FEMALE"),
        @MapItem(key = "6", value = "DIVERS")
    })
    public String salutation;
}
Enter fullscreen mode Exit fullscreen mode

The MapItemsTest tests the MapItems annotation. The test is done on the salutation field.

To demonstrate how the list of @MapItem can be used, I create a HashMap from @MapItem and compare it to an expected HashMap.

class MapItemsTest {

    @Test
    void testMapItems() throws NoSuchFieldException {

        Field field = ExampleDto.class.getDeclaredField("salutation");
        field.setAccessible(true);

        MapItems annotation = field.getAnnotation(MapItems.class);

        Map<String, String> mappingItems = Arrays
                .stream(annotation.items())
                .collect(
                    Collectors.toMap(
                        MapItem::key,
                        MapItem::value
                    )
        );

        assertEquals(
            new HashMap<>() {{
                put("1", "MALE");
                put("2", "FEMALE");
                put("6", "DIVERS");
            }},
            mappingItems
        );
    }
}
Enter fullscreen mode Exit fullscreen mode

Conclusion

Pro

It is a smart solution and easy to implement.

Contra

If the key-value pairs are to be used in a validator, for example, they must be fetched indirectly.

Full example

https://github.com/alaugks/article-annotation-key-value-pairs

Related article

Heroku

Built for developers, by developers.

Whether you're building a simple prototype or a business-critical product, Heroku's fully-managed platform gives you the simplest path to delivering apps quickly — using the tools and languages you already love!

Learn More

Top comments (0)

👋 Kindness is contagious

Explore a trove of insights in this engaging article, celebrated within our welcoming DEV Community. Developers from every background are invited to join and enhance our shared wisdom.

A genuine "thank you" can truly uplift someone’s day. Feel free to express your gratitude in the comments below!

On DEV, our collective exchange of knowledge lightens the road ahead and strengthens our community bonds. Found something valuable here? A small thank you to the author can make a big difference.

Okay