› ~/

Custom Annotations With Swagger Core

2023-11-29

I scratched my head quite a bit before figuring out from the official swagger-core documentation that you can let your annotations define limitations on the Open API specification. The relevant section is extending-core-resolver.

To use a custom annotation you need to configure:

  1. A ModelResolver, which will tell swagger-core how to interpret your annotation.
  2. Register your ModelResolver.

Example

The annotation

I’ll give an example of a range annotation, which will set a min and max value.

1
2
3
4
5
6
7
8
    @Target({ FIELD })
    @Retention(RUNTIME)
    @Constraint(validatedBy = RangeAnnotationValidator.class) // Omitted for brevity.
    @Documented
    public @interface RangeAnnotation {
        int min() default 0;
        int max() default Integer.MAX_VALUE;
    }

A class that uses the annotation

1
2
3
4
    class Custom {
        @RangeAnnotation(min = 0, max = 10)
        public int someField;
    }

ModelResolver

The ModelResolver can be use in two ways:

  1. General method to update all the limitations from the annotation.
  2. Specific methods if you only want to update one limitation at a time.

The following is ModelResolver that uses the former approach.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
    public class RangeAnnotationModelResolver extends ModelResolver {

        public RangeAnnotationModelResolver(ObjectMapper mapper) {
            super(mapper);
        }

        @Override
        public Schema resolve(AnnotatedType annotatedType, ModelConverterContext context, Iterator<ModelConverter> chain) {
            Schema s = chain.next().resolve(annotatedType, context, chain);

            if (s != null) {
                RangeAnnotation annotation = AnnotationsUtils.getAnnotation(RangeAnnotation.class, annotatedType.getCtxAnnotations());
                if (annotation != null) {
                    s.minimum(new BigDecimal(annotation.min()));
                    s.maximum(new BigDecimal(annotation.max()));
                }
                return s;
            }
            return null;
        }
    }

Register the ModelResolver

Once you’ve created your ModelResolver, you need to register it so that swagger-core can use it.

1
    ModelConverters.getInstance().addConverter(new RangeAnnotationModelResolver(Json.mapper()));

That’s all that is needed!

Written by
Andreas