Swagger 2.X Annotations

frantuma edited this page Sep 19, 2018 · 8 revisions

NOTE: Swagger Core 2.X produces OpenApi 3.0 definition files. If you're looking for swagger 1.5.X and OpenApi 2.0, please refer to 1.5.X JAX-RS Setup and [Annotations](Annotations 1.5.X).

Open API Specification Annotations

In order to generate the OpenAPI documentation, swagger-core offers a set of annotations to declare and manipulate the output. The core output is compliant with OpenAPI Specification. A user is not required to be familiar with the full aspects of the OpenAPI Specification in order to use it, but as a reference it may answer a few questions regarding the generated output.

This page introduces the annotations provided by swagger-core. They are grouped into:

The documentation for each annotation is meant as an overview of its usage. Each annotation also has links to its javadocs (both on the header and at the end of the overview).

For your convenience, the javadocs and petstore sample are available as well.

At the very least:

@javax.ws.rs.Path is required at class level to have OpenAPI scan root resources, in compliance with JAX-RS spec.

@javax.ws.rs.<HTTP_METHOD> (e.g. javax.ws.rs.GET) is required at method level.

Note: swagger-jaxrs2 reader engine includes by default also methods of scanned resources which are not annotated with @Operation, as long as a jax-rs @Path is defined at class and/or method level, together with the http method annotation (@GET, @POST, etc).

This behaviour is controlled by configuration property readAllResources which defaults to true. By setting this flag to false only Operation annotated methods are considered.


Quick Annotation Overview

OpenAPI

Name Description
@OpenAPIDefinition General metadata for an OpenAPI definition
@Info Info metadata for an OpenAPI definition
@Contact Properties to describe the contact person for an OpenAPI definition
@License Properties to describe the license for an OpenAPI definition

Operations

Name Description
@Operation Describes an operation or typically a HTTP method against a specific path.
@Parameter Represents a single parameter in an OpenAPI Operation.
@RequestBody Represents the body of the request in an Operation
@ApiResponse Represents the response in an Operation
@Tag Represents tags for an operation or for the OpenAPI definition.
@Server Represents servers for an operation or for the OpenAPI definition.
@Callback Describes a set of requests
@Link Represents a possible design-time link for a response.

Media

Name Description
@Schema Allows the definition of input and output data.
@ArraySchema Allows the definition of input and output data for array types.
@Content Provides schema and examples for a particular media type.

Security

Name Description
@SecurityRequirement Lists the required security schemes to execute this operation.
@SecurityScheme Defines a security scheme that can be used by the operations.

Extensions

Name Description
@Extension Adds an extension with contained properties
@ExtensionProperty Adds custom properties to an extension

Other

Name Description
@Hidden Hides a resource, an operation or a property
@ExternalDocumentation Provides external documentation to a definition element

OpenAPI Annotations

@OpenAPIDefinition

The @OpenAPIDefinition annotation may be used at class level to populate the definition-level fields of the OpenAPI document, as in the example below. It corresponds to the OpenAPI object in the specification, and allows to define info, tags, externalDocs, security requirements and servers.

See also related annotations sections below.

    @OpenAPIDefinition(
            info = @Info(
                    title = "the title",
                    version = "0.0",
                    description = "My API",
                    license = @License(name = "Apache 2.0", url = "http://foo.bar"),
                    contact = @Contact(url = "http://gigantic-server.com", name = "Fred", email = "Fred@gigagantic-server.com")
            ),
            tags = {
                    @Tag(name = "Tag 1", description = "desc 1", externalDocs = @ExternalDocumentation(description = "docs desc")),
                    @Tag(name = "Tag 2", description = "desc 2", externalDocs = @ExternalDocumentation(description = "docs desc 2")),
                    @Tag(name = "Tag 3")
            },
            externalDocs = @ExternalDocumentation(description = "definition docs desc"),
            security = {
                    @SecurityRequirement(name = "req 1", scopes = {"a", "b"}),
                    @SecurityRequirement(name = "req 2", scopes = {"b", "c"})
            },
            servers = {
                    @Server(
                            description = "server 1",
                            url = "http://foo",
                            variables = {
                                    @ServerVariable(name = "var1", description = "var 1", defaultValue = "1", allowableValues = {"1", "2"}),
                                    @ServerVariable(name = "var2", description = "var 2", defaultValue = "1", allowableValues = {"1", "2"})
                            })
            }
    )

See the javadoc for a complete list of supported properties.

@Info

The @Info annotation may be used in io.swagger.v3.oas.annotations.OpenAPIDefinition#info() to populate the Info section of the OpenAPI document, as in the example below. It corresponds to the Info object in the specification.

@OpenAPIDefinition (info = 
    @Info(
              title = "the title",
              version = "0.0",
              description = "My API",
              license = @License(name = "Apache 2.0", url = "http://foo.bar"),
              contact = @Contact(url = "http://gigantic-server.com", name = "Fred", email = "Fred@gigagantic-server.com")
      )
)

See the javadoc for a complete list of supported properties.

@Contact

The @Contact annotation adds contact properties to the @Info section of an OpenAPI definition - corresponding to the Contact object in the specification, as in the example below:

@OpenAPIDefinition (info = 
    @Info(
              title = "the title",
              version = "0.0",
              description = "My API",
              license = @License(name = "Apache 2.0", url = "http://foo.bar"),
              contact = @Contact(url = "http://gigantic-server.com", name = "Fred", email = "Fred@gigagantic-server.com")
      )
)

See the javadoc for a list of supported properties.

@License

The @License annotation adds license properties to the @Info section of an OpenAPI definition - corresponding to the License object in the specification. As in the example above:

@OpenAPIDefinition (info = 
    @Info(
              title = "the title",
              version = "0.0",
              description = "My API",
              license = @License(name = "Apache 2.0", url = "http://foo.bar"),
              contact = @Contact(url = "http://gigantic-server.com", name = "Fred", email = "Fred@gigagantic-server.com")
      )
)

See the javadoc for a list of supported properties.


Operation Annotations

@Operation

The annotation may be used to define a resource method as an OpenAPI Operation, and/or to define additional properties for the Operation.

Note: swagger-jaxrs2 reader engine includes by default also methods of scanned resources which are not annotated with @Operation, as long as a jax-rs @Path is defined at class and/or method level, together with the http method annotation (@GET, @POST, etc).

This behaviour is controlled by configuration property readAllResources which defaults to true. By setting this flag to false only Operation annotated methods are considered.

The following fields can also alternatively be defined at method level (as repeatable annotations in case of arrays), in this case method level annotations take precedence over Operation annotation fields (see related section):

  • tags: @Tag
  • externalDocs: @ExternalDocumentation
  • parameters: @Parameter
  • responses: @ApiResponse
  • requestBody: @RequestBody
  • security: @SecurityRequirement
  • servers: @Server
  • extensions: @Extension
  • hidden: @Hidden

Example 1: A really simple usage would be:

    @GET
    @Operation(summary = "Get users",
            description = "Get list of users")
    public Response getUsers() {..}

Example 2: A sligthly extended example:

    @GET
    @Path("/{username}")
    @Operation(summary = "Get user by user name",
            responses = {
                    @ApiResponse(description = "The user",
                            content = @Content(mediaType = "application/json",
                                    schema = @Schema(implementation = User.class))),
                    @ApiResponse(responseCode = "400", description = "User not found")})
    public Response getUserByName(
            @Parameter(description = "The name that needs to be fetched. Use user1 for testing. ", required = true) @PathParam("username") String username)
            throws ApiException {
        User user = userData.findUserByName(username);
        if (null != user) {
            return Response.ok().entity(user).build();
        } else {
            throw new NotFoundException(404, "User not found");
        }
    }

Example 3: Additional metadata defined:

  @PUT
  @Consumes("application/json")
  @Operation(summary = "Update an existing pet",
          tags = {"pets"},
          security = @SecurityRequirement(
                                  name = "petstore-auth",
                                  scopes = "write:pets"),
          responses = {
                  @ApiResponse(
                     content = @Content(mediaType = "application/json",
                             schema = @Schema(implementation = Pet.class))),
                  @ApiResponse(responseCode = "400", description = "Invalid ID supplied"),
                  @ApiResponse(responseCode = "404", description = "Pet not found"),
                  @ApiResponse(responseCode = "405", description = "Validation exception") }
    )
    public Response updatePet(
      @RequestBody(description = "Pet object that needs to be added to the store", required = true,
                              content = @Content(
                                      schema = @Schema(implementation = Pet.class))) Pet pet) {
        //..
    }

The summary of the annotation is a short description on the API. Since this is displayed in the list of operations in Swagger-UI and the location is limited in size, this should be kept short (preferably shorter than 120 characters). The description allows you to give significantly more details about the operations.

responses is a container for ApiResponse annotations, allowing to define possible responses which can include the return type of the method along with other meta data. Notice that the actual method declaration returns a Response but that is a general-purpose JAX-RS class and not the actual response sent to the user.

If the returned object is the actual result, it can be used directly instead of declaring it in the annotation.

Keep in mind that Java has type erasure, so using generics in the return type may not be parsed properly, and the responses should be used directly.

In the examples above, the @GET or @PUT JAX-RS annotation will be used as the (HTTP) method field of the operation, and the @Path would tell us the path of the operation (operations are grouped under the same path, one for each HTTP method used).

Security related annotation is detailed in section @SecurityRequirement below.

The output for Example 2 would be:

/user/{username}:
    get:
      summary: Get user by user name
      operationId: getUserByName
      parameters:
      - name: username
        in: path
        description: 'The name that needs to be fetched. Use user1 for testing. '
        required: true
        schema:
          type: string
      responses:
        default:
          description: The user
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
        400:
          description: User not found

For further details about this annotation, check out the javadocs and usage examples in tests

@Parameter

The annotation may be used on a method parameter to define it as a parameter for the operation, and/or to define additional properties for the Parameter. It can also be used independently in Operation.parameters() or at method level to add a parameter to the operation, even if not bound to any method parameter. swagger-jaxrs2 reader engine considers this annotation along with JAX-RS annotations, parameter type and context as input to resolve a method parameter into an OpenAPI Operation parameter.

The @Parameter can be used in place of or together with the JAX-RS parameter annotations (@PathParam, @QueryParam, @HeaderParam, @FormParam and @BeanParam). While swagger-core / swagger-jaxrs2 scan these annotations by default, the @Parameter allows to define more details for the parameter.

In the OpenAPI Specification, this translates to the Parameter Object.

An example of usage together with JAX-RS parameter annotation:

public Response login(
           @Parameter(description = "The user name for login", required = true) @QueryParam("username") String username) { ... }

The output would be:

/pet/{petId}:
    get:
      summary: Find pet by ID
      description: Returns a pet when 0 < ID <= 10.  ID > 10 or nonintegers will simulate API error conditions
      operationId: getPetById
      parameters:
      - name: username
        in: query
        description: The user name for login
        required: true
        schema:
          type: string

And an example of usage on its own:

@Path("/subscription/{subscriptionId}")
public Response getSubscription(
           @Parameter(in = "path", name = "subscriptionId",
           			required = true, description = "parameter description",
           			allowEmptyValue = true, allowReserved = true,
           			schema = @Schema(
                                type = "string",
                                format = "uuid",
                                description = "the generated UUID")) String subscriptionId) { ... }

The output would be:

/pet/{petId}:
    get:
      description: parameter description
      operationId: getSubscription
      parameters:
      - name: subscriptionId
        in: path
        description: the generated UUID
        required: true
        schema:
          type: string
          format: uuid
          description: the generated UUID

@Parameter can be also used together with @FormDataParam in multipart scenarios to resolve the operation request body (see also the spec), for example:

    @POST
    @Path("/upload")
    @Consumes(MediaType.MULTIPART_FORM_DATA)
    public Response upload(
            @Parameter(in = ParameterIn.HEADER, name = "Authorization")
            @HeaderParam(HttpHeaders.AUTHORIZATION) String creds,

            @Parameter(schema = @Schema(implementation = Pet.class))
            @FormDataParam("petData") String pet,

            @Parameter(schema = @Schema(type = "string", format = "binary", description = "file 1"))
            @FormDataParam("file1") InputStream file1,

            @Parameter(schema = @Schema(type = "string", format = "binary", description = "file 2"))
            @FormDataParam("file2") InputStream file2,

            @Parameter(schema = @Schema(type = "string", format = "binary", description = "file 3"))
            @FormDataParam("file3") InputStream file3) {
...
}

would resolve to:

  /upload:
    post:
      operationId: upload
      parameters:
      - name: Authorization
        in: header
        schema:
          type: string
      requestBody:
        content:
          multipart/form-data:
            schema:
              type: object
              properties:
                petData:
                  $ref: '#/components/schemas/Pet'
                file1:
                  type: string
                  description: file 1
                  format: binary
                file2:
                  type: string
                  description: file 2
                  format: binary
                file3:
                  type: string
                  description: file 3
                  format: binary
      responses:
        default:
          description: default response
          content:
            application/json: {}
...

For further method parameters bound to the request body, see RequestBody below.

Multiple @Parameter annotations can also be used in parameters field of @Operation annotation or as direct annotation(s) at method level; this can be handy in various scenarios, for example:

  • Wanting to hide a parameter as it is defined and override it with a completely different definition.
  • Describe a parameter that is used by a filter or another resource prior to reaching the JAX-RS implementation.

When defining parameters in parameters field of @Operation annotation or at method level, it's important to set name and in for OpenAPIS's definitions to be proper.

In the sample below we can see an Operation definition with several parameters.

    @GET
    @Path("/")
    @Operation(operationId = "operationId",
            summary = "Operation Summary",
            description = "Operation Description",
            tags = {"Example Tag", "Second Tag"},
            externalDocs =
            @ExternalDocumentation(
                    description = "External documentation description",
                    url = "http://url.com"
            ),
            parameters = {
                    @Parameter(in = "path", name = "subscriptionId",
                            required = true, description = "parameter description",
                            allowEmptyValue = true, allowReserved = true,
                            schema = @Schema(
                                    type = "string",
                                    format = "uuid",
                                    description = "the generated UUID",
                                    accessMode = Schema.AccessMode.READ_ONLY)
                    )},
            responses = {
                    @ApiResponse(
                            responseCode = "200",
                            description = "voila!",
                            content = @Content(
                                    mediaType = "application/json",
                                    schema = @Schema(implementation = ResponsesResource.SampleResponseSchema.class)
                            )
                    ),
                    @ApiResponse(
                            responseCode = "default",
                            description = "boo",
                            content = @Content(
                                    mediaType = "*/*",
                                    schema = @Schema(implementation = ResponsesResource.GenericError.class)
                            )
                    )
            }
    )
    public Response getSummaryAndDescription() {
        return Response.ok().entity("ok").build();
    }
openapi: 3.0.1
tags:
- name: Example Tag
  description: Example Tag
- name: Second Tag
  description: Second Tag
paths:
  /:
    get:
      tags:
      - Example Tag
      - Second Tag
      summary: Operation Summary
      description: Operation Description
      externalDocs:
        description: External documentation description
        url: http://url.com
      operationId: operationId
      parameters:
      - name: subscriptionId
        in: path
        description: parameter description
        required: true
        allowEmptyValue: true
        allowReserved: true
        schema:
          type: string
          description: the generated UUID
          format: uuid
          readOnly: true
      responses:
        200:
          description: voila!
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SampleResponseSchema'
        default:
          description: boo
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/GenericError'
components:
  schemas:
    GenericError:
      type: object
    string:
      type: string
      description: the generated UUID
      format: uuid
      readOnly: true
    SampleResponseSchema:
      type: object

The same result is obtained applying the annotation at method level.

    @GET
    @Path("/")
    @Operation(operationId = "operationId",
            summary = "Operation Summary",
            description = "Operation Description",
            tags = {"Example Tag", "Second Tag"},
            externalDocs =
            @ExternalDocumentation(
                    description = "External documentation description",
                    url = "http://url.com"
            ),
            responses = {
                    @ApiResponse(
                            responseCode = "200",
                            description = "voila!",
                            content = @Content(
                                    mediaType = "application/json",
                                    schema = @Schema(implementation = ResponsesResource.SampleResponseSchema.class)
                            )
                    ),
                    @ApiResponse(
                            responseCode = "default",
                            description = "boo",
                            content = @Content(
                                    mediaType = "*/*",
                                    schema = @Schema(implementation = ResponsesResource.GenericError.class)
                            )
                    )
            }
    )
    @Parameter(in = "path", name = "subscriptionId",
        required = true, description = "parameter description",
        allowEmptyValue = true, allowReserved = true,
        schema = @Schema(
                type = "string",
                format = "uuid",
                description = "the generated UUID",
                accessMode = Schema.AccessMode.READ_ONLY)
    )
    public Response getSummaryAndDescription() {
        return Response.ok().entity("ok").build();
    }

For further details about this annotation, check out the javadocs and usage examples in tests

@RequestBody

The annotation may be used on a method parameter to define it as the Request Body of the operation, and/or to define additional properties for such request body. It maps to OpenAPI spec RequestBody

It can also be used at method level or as field of Operation#requestBody, in which case it will not be bound to the specific parameter.

Also without a @RequestBody annotated parameter and with no @RequestBody annotation at method level or as field of Operation#requestBody, if a parameter is annotated with @Parameter with no in field specified and no JAX-RS annotation (@QueryParam, @HeaderParam, @BeanParam), the parameter is resolved as a request body.This happens only when the http method is associated with the @PUT or @POST verb. In case of multiple such parameters, only the first is considered.

public Response addPet(
        @Parameter(description = "Pet object that needs to be added to the store", required = true) Pet pet) { ... }

The output would be:

      requestBody:
        description: Pet object that needs to be added to the store
          content:
            application/json:
             schema:
              $ref: '#/components/schemas/Pet'
          required: true

We can add more meta data with the @RequestBody annotation:

@POST
        @Path("/user")
        @Operation(summary = "Create user",
                description = "This can only be done by the logged in user.")
        public Response methodWithRequestBodyAndTwoParameters(
                @RequestBody(description = "Created user object", required = true,
                        content = @Content(
                                schema = @Schema(implementation = User.class))) User user,
                @QueryParam("name") String name, @QueryParam("code") String code)
                { ... }

The output would be:

  post:
      summary: Create user
        description: This can only be done by the logged in user.
        operationId: methodWithRequestBodyAndTwoParameters
      parameters:
      - name: name
        in: query
        schema:
        type: string
      - name: code
        in: query
        schema:
        type: string
      requestBody:
        description: Created user object
        content:
        '*/*':
          schema:
            $ref: '#/components/schemas/User'
            required: true
      responses:
        default:
          description: no description

The @RequestBody might be affected by the @Consumes annotation: for every media type defined there will be an associated mediaType in the RequestBody content.

@POST
       @Path("/pet")
       @Operation(summary = "Create pet",
               description = "Creating pet.")
       @Consumes({"application/json", "application/xml"})
       public Response methodWithTwoRequestBodyWithoutAnnotationAndTwoConsumes(
               Pet pet, User user) { .. }

The output would be:

post:
  summary: Create pet
  description: Creating pet.
  operationId: methodWithTwoRequestBodyWithoutAnnotationAndTwoConsumes
  requestBody:
    content:
      application/json:
        schema:
          $ref: '#/components/schemas/Pet'
      application/xml:
        schema:
          $ref: '#/components/schemas/Pet'
  responses:
    default:
      description: no description

For further details about this annotation, usage and edge cases, check out the javadocs) and usage examples in specific test class and other tests.

@ApiResponse

The annotation may be used at method level or as field of @Operation to define one or more responses of the Operation. It maps to OpenAPI spec ApiResponse

swagger-jaxrs2 reader engine considers this annotation along with method return type and context as input to resolve the OpenAPI Operation responses, along with the response body content/schema if applicable.

If no @ApiResponse is provided at method level or in the @Operation annotation, a default response will be generated, inferring when possible the content/schema from the method return type.

A simple example of usage:

    @DELETE
    @Path("/{username}")
    @Operation(summary = "Delete user",
            description = "This can only be done by the logged in user.")
    @ApiResponse(responseCode = "200", description = "user deteled")
    @ApiResponse(responseCode = "400", description = "Invalid username supplied")
    @ApiResponse(responseCode = "404", description = "User not found")                    
    public Response deleteUser(
            @Parameter(description = "The name that needs to be deleted", required = true) @PathParam("username") String username) {...}

or

    @DELETE
    @Path("/{username}")
    @Operation(summary = "Delete user",
            description = "This can only be done by the logged in user.",
            responses = {
                    @ApiResponse(responseCode = "200", description = "user deteled"),
                    @ApiResponse(responseCode = "400", description = "Invalid username supplied"),
                    @ApiResponse(responseCode = "404", description = "User not found")})
    public Response deleteUser(
            @Parameter(description = "The name that needs to be deleted", required = true) @PathParam("username") String username) {...}

In this case the response would be:

    delete:
      summary: Delete user
      description: This can only be done by the logged in user.
      operationId: deleteUser
      parameters:
      - name: username
        in: path
        description: The name that needs to be deleted
        required: true
        schema:
          type: string
      responses:
        200:
          description: user deteled
        400:
          description: Invalid username supplied
        404:
          description: User not found

A more complex example, providing schema and examples:

        @Operation(
                summary = "Simple get operation",
                description = "Defines a simple get operation with no inputs and a complex",
                operationId = "getWithPayloadResponse",
                deprecated = true
        )
        @ApiResponse(
                responseCode = "200",
                description = "voila!",
                content = @Content(
                        mediaType = "application/json",
                        schema = @Schema(implementation = SampleResponseSchema.class)
                ))
        @ApiResponse(
                description = "boo",
                content = @Content(
                        mediaType = "*/*",
                        schema = @Schema(implementation = GenericError.class),
                        examples = {
                                @ExampleObject(name = "boo", value = "example",
                                        summary = "example of boo", externalValue = "example of external value")
                        }

                )
        )        
        @Path("/path")
        @GET
        public void simpleGet() {
        }
get:
      summary: Simple get operation
      description: Defines a simple get operation with no inputs and a complex
      operationId: getWithPayloadResponse
      responses:
        200:
          description: voila!
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/SampleResponseSchema'
        default:
          description: boo
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/GenericError'
              examples:
                boo:
                  summary: example of boo
                  description: boo
                  value: example
                  externalValue: example of external value
      deprecated: true

An example with no @ApiRepsonse defined:

    @GET
    @Operation(description = "returns a value")
    @Path("/findAll")
    public SimpleResponse getSimpleResponseWithParameters(...){ ... }

In this case the response would be resolved from the return type:

responses:
  default:
    description: no description
    content:
      '*/*':
        schema:
          $ref: '#/components/schemas/SimpleResponse'

The @Produces annotation can affect the contents of this annotation; @Produces response media types are added to the content of operation responses:

@Produces({"application/json", "application/xml"})
public class UserResource {
  @GET
  @Path("/login")
  @Operation(summary = "Logs user into the system",
          responses = {
                  @ApiResponse(description = "Successfully logged in",
                          content = @Content(schema = @Schema(implementation = String.class))),
                  @ApiResponse(responseCode = "400", description = "Invalid username/password supplied")})
  public Response loginUser( ... ){ ... }
}

In this case the result would be:

/user/login:
  get:
    summary: Logs user into the system
    operationId: loginUser
    parameters:
    - name: username
      in: query
      description: The user name for login
      required: true
      schema:
        type: string
    - name: password
      in: query
      description: The password for login in clear text
      required: true
      schema:
        type: string
    responses:
      default:
        description: Successfully logged in
        content:
          application/json:
            schema:
              type: string
          application/xml:
            schema:
              type: string
      400:
        description: Invalid username/password supplied

For further details about this annotation, usage and edge cases, check out the javadocs @ApiResponse) and usage examples in specific test class and other tests.

@Tag

The annotation may be applied at class or method level, or in @Operation#tags() to define tags for the single operation (when applied at method level) or for all operations of a class (when applied at class level).

When applied at method or class level, if only a name is provided, the tag will be added to operation only; if additional fields are also defined, like description or externalDocs, the Tag will also be added to openAPI.tags field.

It maps to OpenAPI spec Tag

A full example:

@OpenAPIDefinition(tags = {
        @Tag(name = "Definition First Tag"),
        @Tag(name = "Definition Second Tag full", description = "desc definition")
})
@Tag(name = "Second Tag")
@Tag(name = "Fourth Tag Full", description = "desc class", externalDocs = @ExternalDocumentation(description = "docs desc class"))
@Tag(name = "Fifth Tag Full", description = "desc class", externalDocs = @ExternalDocumentation(description = "docs desc class"))
@Tag(name = "Sixth Tag")
public class TagsResource {

    @GET
    @Path("/")
    @Operation(tags = {"Example Tag", "Second Tag"})
    @Tag(name = "Third Tag")
    @Tag(name = "Second Tag")
    @Tag(name = "Fourth Tag Full", description = "desc", externalDocs = @ExternalDocumentation(description = "docs desc"))
    public Response getTags() {
        return Response.ok().entity("ok").build();
    }
}

Resolves into:

openapi: 3.0.1
tags:
- name: Definition First Tag
- name: Definition Second Tag full
  description: desc definition
- name: Fourth Tag Full
  description: desc
  externalDocs:
    description: docs desc
- name: Fifth Tag Full
  description: desc class
  externalDocs:
    description: docs desc class
paths:
  /:
    get:
      tags:
      - Third Tag
      - Second Tag
      - Fourth Tag Full
      - Example Tag
      - Fifth Tag Full
      - Sixth Tag
      operationId: getTags
      responses:
        default:
          description: default response

It can also be used in @OpenAPIDefinition#tags() to define spec level tags:

    @OpenAPIDefinition(
            tags = {
                    @Tag(name = "Tag 1", description = "desc 1", externalDocs = @ExternalDocumentation(description = "docs desc")),
                    @Tag(name = "Tag 2", description = "desc 2", externalDocs = @ExternalDocumentation(description = "docs desc 2")),
                    @Tag(name = "Tag 3")
            }
    )
    static class ClassWithAnnotation {..}
openapi: 3.0.1
tags:
- name: Tag 1
  description: desc 1
  externalDocs:
    description: docs desc
- name: Tag 2
  description: desc 2
  externalDocs:
    description: docs desc 2
- name: Tag 3

For further details about this annotation, usage and edge cases, check out the javadocs @Tag) and usage examples in specific test class and other tests.

@Server

The annotation may be applied at class or method level, or in @Operation#servers() to define servers for the single operation (when applied at method level) or for all operations of a class (when applied at class level).

It maps to OpenAPI spec Server

A full example:

@OpenAPIDefinition(
    servers = {
        @Server(
            description = "definition server 1",
            url = "http://definition1",
            variables = {
                @ServerVariable(name = "var1", description = "var 1", defaultValue = "1", allowableValues = {"1", "2"}),
                @ServerVariable(name = "var2", description = "var 2", defaultValue = "1", allowableValues = {"1", "2"})
            })
    }
)
@Server(
        description = "class server 1",
        url = "http://class1",
        variables = {
                @ServerVariable(name = "var1", description = "var 1", defaultValue = "1", allowableValues = {"1", "2"}),
                @ServerVariable(name = "var2", description = "var 2", defaultValue = "1", allowableValues = {"1", "2"})
        })
@Server(
        description = "class server 2",
        url = "http://class2",
        variables = {
                @ServerVariable(name = "var1", description = "var 1", defaultValue = "1", allowableValues = {"1", "2"})
        })
public class ServersResource {

    @GET
    @Path("/")
    @Operation(servers = {
            @Server(
                    description = "operation server 1",
                    url = "http://op1",
                    variables = {
                            @ServerVariable(name = "var1", description = "var 1", defaultValue = "1", allowableValues = {"1", "2"})
                    })
    })
    @Server(
            description = "method server 1",
            url = "http://method1",
            variables = {
                    @ServerVariable(name = "var1", description = "var 1", defaultValue = "1", allowableValues = {"1", "2"})
            })
    @Server(
            description = "method server 2",
            url = "http://method2"
    )

    public Response getServers() {
        return Response.ok().entity("ok").build();
    }
}

Resolves into:

openapi: 3.0.1
servers:
- url: http://definition1
  description: definition server 1
  variables:
    var1:
      description: var 1
      enum:
      - "1"
      - "2"
      default: "1"
    var2:
      description: var 2
      enum:
      - "1"
      - "2"
      default: "1"
paths:
  /:
    get:
      operationId: getServers
      responses:
        default:
          description: default response
      servers:
      - url: http://class1
        description: class server 1
        variables:
          var1:
            description: var 1
            enum:
            - "1"
            - "2"
            default: "1"
          var2:
            description: var 2
            enum:
            - "1"
            - "2"
            default: "1"
      - url: http://class2
        description: class server 2
        variables:
          var1:
            description: var 1
            enum:
            - "1"
            - "2"
            default: "1"
      - url: http://method1
        description: method server 1
        variables:
          var1:
            description: var 1
            enum:
            - "1"
            - "2"
            default: "1"
      - url: http://method2
        description: method server 2
        variables: {}
      - url: http://op1
        description: operation server 1
        variables:
          var1:
            description: var 1
            enum:
            - "1"
            - "2"
            default: "1"

It can also be used in @OpenAPIDefinition#servers() to define spec level servers:

    @OpenAPIDefinition(
            servers = {
                    @Server(
                            description = "server 1",
                            url = "http://foo",
                            variables = {
                                    @ServerVariable(name = "var1", description = "var 1", defaultValue = "1", allowableValues = {"1", "2"}),
                                    @ServerVariable(name = "var2", description = "var 2", defaultValue = "1", allowableValues = {"1", "2"})
                            })
            }
    )
    static class ClassWithAnnotation {..}

openapi: 3.0.1
servers:
- url: http://foo
  description: server 1
  variables:
    var1:
      description: var 1
      enum:
      - "1"
      - "2"
      default: "1"
    var2:
      description: var 2
      enum:
      - "1"
      - "2"
      default: "1"

For further details about this annotation, usage and edge cases, check out the javadocs @Server) and usage examples in specific test class and other tests.

Note: class level servers annotation are supported in latest 2.0.0-SNAPSHOT and next release

@Callback

The annotation may be used at method level to add one ore more callbacks to the operation definition.

It maps to OpenAPI spec Callback

A usage example:

    @Path("/test")
    @POST
    @Callback(
            callbackUrlExpression = "http://$request.query.url",
            name = "subscription",
            operation = {
                    @Operation(
                            method = "post",
                            description = "payload data will be sent",
                            parameters = {
                                    @Parameter(in = ParameterIn.PATH, name = "subscriptionId", required = true, schema = @Schema(
                                            type = "string",
                                            format = "uuid",
                                            description = "the generated UUID",
                                            accessMode = Schema.AccessMode.READ_ONLY
                                    ))
                            },
                            responses = {
                                    @ApiResponse(
                                            responseCode = "200",
                                            description = "Return this code if the callback was received and processed successfully"
                                    ),
                                    @ApiResponse(
                                            responseCode = "205",
                                            description = "Return this code to unsubscribe from future data updates"
                                    ),
                                    @ApiResponse(
                                            responseCode = "default",
                                            description = "All other response codes will disable this callback subscription"
                                    )
                            }),
                    @Operation(
                            method = "get",
                            description = "payload data will be received"
                    ),
                    @Operation(
                            method = "put",
                            description = "payload data will be sent"
                    )})
    @Operation(description = "subscribes a client to updates relevant to the requestor's account, as " +
            "identified by the input token.  The supplied url will be used as the delivery address for response payloads")
    public SubscriptionResponse subscribe(@Schema(required = true, description = "the authentication token " +
            "provided after initially authenticating to the application") @HeaderParam("x-auth-token") String token,
                                          @Schema(required = true, description = "the URL to call with response " +
                                                  "data") @QueryParam("url") String url) {
        return null;
    }

    static class SubscriptionResponse {
        private String subscriptionUuid;
    }
    

The output would be:

callbacks:
  subscription:
    http://$request.query.url:
      post:
        description: payload data will be sent
        parameters:
        - name: subscriptionId
          in: path
          required: true
          schema:
            type: string
            description: the generated UUID
            format: uuid
            readOnly: true
        responses:
          200:
            description: Return this code if the callback was received and processed successfully
          205:
            description: Return this code to unsubscribe from future data updates
          default:
            description: All other response codes will disable
            

For further details about this annotation, usage and edge cases, check out the javadocs @Callback) and usage examples in specific test resource class and test class.

@Link

The annotation may be applied in @ApiResponse#links() to add OpenAPI links to a response.

Please see OpenAPI spec Link for futher details.

A usage example:

static class ClassWithOperationAndLinks {
        @Path("/users")
        @Operation(operationId = "getUser",
                responses = {
                        @ApiResponse(description = "test description",
                                content = @Content(mediaType = "*/*", schema = @Schema(ref = "#/components/schemas/User")),
                                links = {
                                        @Link(
                                                name = "address",
                                                operationId = "getAddress",
                                                parameters = @LinkParameter(
                                                        name = "userId",
                                                        expression = "$request.query.userId"))
                                })}
        )
        @GET
        public User getUser(@QueryParam("userId") String userId) {
            return null;
        }

        @Path("/addresses")
        @Operation(operationId = "getAddress",

                responses = {
                        @ApiResponse(content = @Content(mediaType = "*/*",
                                schema = @Schema(ref = "#/components/schemas/Address")),
                                description = "test description")
                })
        @GET
        public Address getAddress(@QueryParam("userId") String userId) {
            return null;
        }
    }
    

The output would be:

paths:
  /users:
    get:
      operationId: getUser
      parameters:
      - name: userId
        in: query
        schema:
          type: string
      responses:
        default:
          description: test description
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/User'
          links:
            address:
              operationId: getAddress
              parameters:
                userId: $request.query.userId
  /addresses:
    get:
      operationId: getAddress
      parameters:
      - name: userId
        in: query
        schema:
          type: string
      responses:
        default:
          description: test description
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/Address'
            

For further details about this annotation, usage and edge cases, check out the javadocs @Link and test class.


Media Annotations

@Schema

The annotation may be used to define a Schema for a set of elements of the OpenAPI spec, and/or to define additional properties for the schema. It is applicable e.g. to parameters, schema classes (aka "models"), properties of such models, request and response content, header.

swagger-core resolver and swagger-jaxrs2 reader engine consider this annotation along with JAX-RS annotations, element type and context as input to resolve the annotated element into an OpenAPI schema definition for such element.

The annotation may be used also to override partly (e.g. the name) or fully (e.g providing a completely different representation) the schema of an element; for example if a specific class is provided as value of Schema#implementation() it will override the element type.

The annotation @ArraySchema shall be used for array elements; ArraySchema and Schema cannot coexist.

See also OpenAPI spec Schema in the OpenAPI Specification.

@Schema can be used to annotate directly a model bean:

@Schema(name="DifferentModel", description="Sample model for the documentation")
class OriginalModel {...}
 "DifferentModel": {
      "description": "Sample model for the documentation",
      .
      .
  }

And/Or a schema property:

 @Schema(description = "pet status in the store", allowableValues =  {"available","pending","sold"})
  public String getStatus() {
    return status;
  }

And/Or in the schema field of @Parameter, @Header or @Content annotations

@ApiResponse(description = "Pets matching criteria",
                           content = @Content(schema = @Schema(implementation = Pet.class))
                   ),

For further details about this annotation, usage and edge cases, check out:

@ArraySchema

The annotation may be used to define a schema of type "array" for a set of elements of the OpenAPI spec, and/or to define additional properties for the schema. It is applicable e.g. to parameters, schema classes (aka "models"), properties of such
models, request and response content, header.

swagger-core resolver and swagger-jaxrs2 reader engine consider this annotation along with JAX-RS annotations, element type and context as input to resolve the annotated element into an OpenAPI schema definition for such element.

The annotation may be used also to override partly (e.g. the name) or fully (e.g providing a completely different representation) the schema of an element; for example if a specific class is provided as value of Schema#implementation() it will override the element type.

The annotation @Schema shall be used for non array elements; ArraySchema and Schema cannot coexist.

See also OpenAPI spec Schema in the OpenAPI Specification.

An example applied to a response:

    @Operation(
            summary = "Get a list of users",
            description = "Get a list of users registered in the system",
            responses = {@ApiResponse(
                    responseCode = "200",
                    description = "The response for the user request",
                    content = {
                            @Content(
                                    mediaType = "application/json",
                                    array = @ArraySchema(schema = @Schema(implementation = User.class))
                            )
                    })
            }
    )
    @GET
    @SecurityRequirement(name = "JWT")
    @Path("/user")
    public List<User> getUsers() {
        return null;
    }

    class User {
        public String foo;
    }
    

with output:

openapi: 3.0.1
paths:
  /user:
    get:
      summary: Get a list of users
      description: Get a list of users registered in the system
      operationId: getUsers
      responses:
        200:
          description: The response for the user request
          content:
            application/json:
              schema:
                type: array
                items:
                  $ref: '#/components/schemas/User'
      security:
      - JWT: []
components:
  schemas:
    User:
      type: object
      properties:
        foo:
          type: string

For further details about this annotation, usage and edge cases, check out:

@Content

The annotation may be used to define the content/media type of a parameter, request or response, by definining it as field of @Parameter, RequestBody and ApiResponse annotations, and matches related OpenAPI specification content property of Parameter Object, Request Body Object and Response Object.

If @Content#schema is defined, swagger-jaxrs2 reader engine will consider it along with JAX-RS annotations, element type and context as input to resolve the annotated element into an OpenAPI schema definition for such element.

See also OpenAPI spec Media Type in the OpenAPI Specification.

@ApiResponse(
    content = @Content(mediaType = "application/json",
            schema = @Schema(implementation = Pet.class)))
responses:
  default:
    content:
      application/json:
        schema:
          $ref: '#/components/schemas/Pet'
  400:
    description: Invalid status value

For further details about this annotation, usage and edge cases, check out:


Security Annotations

@SecurityScheme

The annotation may be used at class level (also on multiple classes) to add securitySchemes to spec components section.

See also OpenAPI spec Security Scheme in the OpenAPI Specification.

An example:

@SecurityScheme(name = "myOauth2Security",
           type = "oauth2",
           in = "header",
           flows = @OAuthFlows(
                   implicit = @OAuthFlow(authorizationUrl = "http://url.com/auth",
                           scopes = @Scopes(name = "write:pets", description = "modify pets in your account"))))
   static class OAuth2SchemeOnClass { ... }

The output would be:

components:
  securitySchemes:
    myOauth2Security:
      type: oauth2
      in: header
      flows:
        implicit:
          authorizationUrl: http://url.com/auth
          scopes:
            name: write:pets
            description: modify pets in your account

For further details about this annotation, usage and edge cases, check out:

@SecurityRequirement

The annotation may be applied at class or method level, or in @Operation#security() to define security requirements for the single operation (when applied at method level) or for all operations of a class (when applied at class level).

It can also be used in @OpenAPIDefinition#security() to define spec level security.

See also OpenAPI spec Security Requirement in the OpenAPI Specification.

An example:

@SecurityScheme(name = "myOauth2Security",
        type = "oauth2",
        in = "header",
        flows = @OAuthFlows(
                implicit = @OAuthFlow(authorizationUrl = "http://url.com/auth",
                        scopes = @Scopes(name = "write:pets", description = "modify pets in your account"))))
static class SecurityRequirementOnClass {
    @Operation(description = "operation")
    @SecurityRequirement(name = "myOauth2Security", scopes = "write: read")
    @GET
    @Path("/")
    public Response getResponse(){
        return null;
    }
}

The output would be:

openapi: 3.0.1
paths:
  /:
    get:
      description: operation
      operationId: getResponse
      responses:
        default:
          description: no description
          content:
            '*/*':
              schema:
                $ref: '#/components/schemas/Response'
      security:
      - myOauth2Security:
        - 'write: read'
components:
  schemas:
    Response:
      type: object
      properties:
        context:
          type: object
          additionalProperties: {}
        cancelled:
          type: boolean
        done:
          type: boolean
  securitySchemes:
    myOauth2Security:
      type: oauth2
      in: header
      flows:
        implicit:
          authorizationUrl: http://url.com/auth
          scopes:
            name: write:pets
            description: modify pets in your account

For further details about this annotation, usage and edge cases, check out:


Extensions Annotations

@Extension

The extension annotation allows adding vendor extensions to an OpenAPI definition.

See test resource classes for usage examples

@ExtensionProperty

An individual property within an extension - see previous @Extension section for examples.

Note that @ExtensionProperty boolean field parseValue, when set to true, allows to have the extension value parsed and serialized as JSON/YAML:

@Operation(extensions = {
    @Extension(properties = {
            @ExtensionProperty(name = "codes", value = "[\"11\", \"12\"]", parseValue = true),
            @ExtensionProperty(name = "name", value = "Josh")})
})
public Response getSummaryAndDescription() {...}

will be resolved into:

x-name: "Josh"
x-codes:
- "11"
- "12"

Other Annotations

@Hidden

Marks a given resource, class or bean type as hidden, skipping while reading / resolving.

An example:

    @Path("/user")
    @Produces({"application/json", "application/xml"})
    public class HiddenAnnotatedUserResourceMethodAndData {
        UserData userData = new UserData();

        @POST
        @Hidden
        @Operation(summary = "Create user",
                description = "This can only be done by the logged in user.")
        @Path("/1")
        public Response createUser(
                @Parameter(description = "Created user object", required = true) User user) {
            userData.addUser(user);
            return Response.ok().entity("").build();
        }

        @POST
        @Operation(summary = "Create user",
                description = "This can only be done by the logged in user.")
        @Path("/2")
        public Response createUserWithHiddenBeanProperty(
                @Parameter(description = "Created user object", required = true) UserResourceBean user) {
            return Response.ok().entity("").build();
        }
    }
    

The output would be:

openapi: 3.0.1
paths:
  /user/2:
    post:
      summary: Create user
      description: This can only be done by the logged in user.
      operationId: createUserWithHiddenBeanProperty
      requestBody:
        description: Created user object
        content:
          '*/*':
            schema:
              $ref: '#/components/schemas/UserResourceBean'
        required: true
      responses:
        default:
          description: default response
components:
  schemas:
    UserResourceBean:
      type: object
      properties:
        foo:
          type: string
         

For further details about this annotation, usage and edge cases, check out:

@ExternalDocumentation

The annotation may be used at method level or as field of Operation#externalDocs to add a reference to an external resource for extended documentation of an Operation.

It may also be used to add external documentation to Tag, Header or Schema, or as field of OpenAPIDefinition#externalDocs.

An example:

    @Path("/user")
    @Produces({"application/json", "application/xml"})
    public class HiddenAnnotatedUserResourceMethodAndData {
        UserData userData = new UserData();

        @POST
        @Hidden
        @Operation(summary = "Create user",
                description = "This can only be done by the logged in user.")
        @Path("/1")
        public Response createUser(
                @Parameter(description = "Created user object", required = true) User user) {
            userData.addUser(user);
            return Response.ok().entity("").build();
        }

        @POST
        @Operation(summary = "Create user",
                description = "This can only be done by the logged in user.")
        @Path("/2")
        public Response createUserWithHiddenBeanProperty(
                @Parameter(description = "Created user object", required = true) UserResourceBean user) {
            return Response.ok().entity("").build();
        }
    }
    

The output would be:

openapi: 3.0.1
paths:
  /user/2:
    post:
      summary: Create user
      description: This can only be done by the logged in user.
      operationId: createUserWithHiddenBeanProperty
      requestBody:
        description: Created user object
        content:
          '*/*':
            schema:
              $ref: '#/components/schemas/UserResourceBean'
        required: true
      responses:
        default:
          description: default response
components:
  schemas:
    UserResourceBean:
      type: object
      properties:
        foo:
          type: string
         

For further details about this annotation, usage and edge cases, check out:

Clone this wiki locally
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.
Press h to open a hovercard with more details.