Skip to content

Custom Operation Builder Plugin

Indra Basak edited this page May 3, 2017 · 9 revisions

Operation Plugin

Springfox provides a OperationBuilderPlugin to extend the Swagger model at the REST operation level. An operation is considered as an unique combination of a path and a HTTP method. In terms of Spring, any Java method annotated with @RequestMapping.

In this example, we will create a custom method-level annotation which will generate a new JSON object named Since. The new JSON object is not reflected on the Swagger UI.

Maven Dependency Changes

Make sure to add the Springfox Spi library.

<dependency>
    <groupId>io.springfox</groupId>
    <artifactId>springfox-spi</artifactId>
    <version>2.6.1</version>
</dependency>

Custom Annotation

Our example annotation, ApiOperationSince, is at the method-level and it has two attributes value and description. Both the attributes are of string type. The value specifies the product version when the operation was added to the API specification. The description is a short description of the release.

@Target(ElementType.METHOD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ApiOperationSince {
    String value() default "";

    String description() default "";
}

Usage

The @ApiOperationSince is used at the operation level. Here is an example of the annotation used on create method of the TigerController. For example, the create operation was added in Release 1.0, the value is stated as 1.0. The description is a short description of the release.

Given this annotated method,

@ApiOperationSince(value = "1.0", description = "Release 1.0")
@RequestMapping(method = RequestMethod.POST, value = TIGER_URL,
        consumes = MediaType.APPLICATION_JSON_VALUE,
        produces = MediaType.APPLICATION_JSON_VALUE)
@ResponseStatus(HttpStatus.CREATED)
public Tiger create(
        @ApiParam(value = "Transaction ID as UUID", defaultValue = TYPE_UUID)
        @RequestHeader(HEADER_TXN_ID) UUID txnId,
        @ApiParam(value = "ISO formatted Transaction Date", defaultValue = TYPE_ISO_DATE_TIME)
        @RequestHeader(HEADER_TXN_DATE) @DateTimeFormat(iso = DateTimeFormat.ISO.DATE_TIME) Date txnDate,
        @RequestBody MenagerieRequest request) {
    return service.create(request);
}

The output of @ApiOperationSince will appear as a Since JSON object. Here is an example:

/tigers: {
    post: {
        tags: [
            "A2"
        ],
        summary: "Creates a Tiger.",
        description: "Requires a Tiger name and gender.",
        operationId: "createUsingPOST_2",
        ...
        Since: {
            description: "Release 1.0",
            value: "1.0"
        }
    }
}

Custom Plugin

The example class SinceOperationBuilder implements OperationBuilderPlugin interface. In the method apply, check if the operation is annotated with @ApiOperationSince. If the custom annotation exists, creates a new ObjectVendorExtension which will generate a new JSON model called Since.

@Component
@Order(SwaggerPluginSupport.SWAGGER_PLUGIN_ORDER + 1002)
@Slf4j
public class SinceOperationBuilder implements OperationBuilderPlugin {

    @Override
    public void apply(OperationContext context) {
        Optional<ApiOperationSince> annotation =
                context.findAnnotation(ApiOperationSince.class);
        if (annotation.isPresent() && annotation.get().value() != null) {
            String value = annotation.get().value();
            String description = annotation.get().description();
            ObjectVendorExtension ext = new ObjectVendorExtension("Since");
            if (description != null) {
                ext.addProperty(
                        new StringVendorExtension("description", description));
            }
            ext.addProperty(new StringVendorExtension("value", value));

            context.operationBuilder().extensions(
                    Collections.singletonList(ext));
            log.debug("Added since ", value);
        }
    }

    @Override
    public boolean supports(DocumentationType documentationType) {
        return true;
    }
}