CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/maven-io-swagger-core-v3--swagger-annotations

Swagger Core annotations library providing OpenAPI 3.x annotations for Java applications, enabling developers to document REST APIs with metadata annotations

Pending
Overview
Eval results
Files

responses.mddocs/

Response Documentation

This document covers annotations for documenting API responses, including status codes, headers, content types, and comprehensive response scenarios.

Imports

import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.headers.Header;
import io.swagger.v3.oas.annotations.links.Link;
import io.swagger.v3.oas.annotations.links.LinkParameter;
import io.swagger.v3.oas.annotations.media.Content;
import io.swagger.v3.oas.annotations.media.Schema;
import io.swagger.v3.oas.annotations.media.ExampleObject;

ApiResponse

Defines comprehensive operation response documentation including status codes, descriptions, headers, content types, and links to related operations.

Basic Response Documentation

@GetMapping("/pets/{id}")
@Operation(summary = "Get pet by ID", tags = {"pets"})
@ApiResponse(
    responseCode = "200",
    description = "Successful operation - Pet found and returned",
    headers = {
        @Header(
            name = "X-Rate-Limit-Remaining",
            description = "Number of requests remaining in current time window",
            schema = @Schema(type = "integer", minimum = "0")
        ),
        @Header(
            name = "X-Rate-Limit-Reset",
            description = "Time when rate limit resets (Unix timestamp)",
            schema = @Schema(type = "integer", format = "int64")
        )
    },
    content = @Content(
        mediaType = "application/json",
        schema = @Schema(implementation = Pet.class),
        examples = {
            @ExampleObject(
                name = "successfulPetResponse",
                summary = "Successful pet retrieval",
                description = "Example of a successfully retrieved pet",
                value = """
                    {
                        "id": 123,
                        "name": "Fluffy",
                        "category": {
                            "id": 1,
                            "name": "Dogs"
                        },
                        "status": "available",
                        "tags": ["friendly", "trained"],
                        "photoUrls": ["https://example.com/photos/fluffy.jpg"]
                    }
                    """
            )
        }
    )
)
@ApiResponse(
    responseCode = "400",
    description = "Invalid pet ID supplied - ID must be a positive integer",
    content = @Content(
        mediaType = "application/json",
        schema = @Schema(implementation = ErrorResponse.class),
        examples = @ExampleObject(
            name = "invalidIdError",
            summary = "Invalid ID error",
            value = """
                {
                    "error": "INVALID_PARAMETER",
                    "message": "Pet ID must be a positive integer",
                    "field": "id",
                    "code": 400
                }
                """
        )
    )
)
@ApiResponse(
    responseCode = "404",
    description = "Pet not found - No pet exists with the provided ID",
    content = @Content(
        mediaType = "application/json",
        schema = @Schema(implementation = ErrorResponse.class),
        examples = @ExampleObject(
            name = "petNotFoundError",
            summary = "Pet not found error",
            value = """
                {
                    "error": "RESOURCE_NOT_FOUND",
                    "message": "No pet found with ID 123",
                    "resourceType": "Pet",
                    "resourceId": "123",
                    "code": 404
                }
                """
        )
    )
)
public ResponseEntity<Pet> getPetById(@PathVariable Long id) {
    Pet pet = petService.findById(id);
    return ResponseEntity.ok()
        .header("X-Rate-Limit-Remaining", "99")
        .header("X-Rate-Limit-Reset", String.valueOf(System.currentTimeMillis() + 3600000))
        .body(pet);
}

Multiple Content Types

@GetMapping(value = "/pets/{id}", produces = {"application/json", "application/xml", "text/plain"})
@ApiResponse(
    responseCode = "200",
    description = "Pet information in requested format",
    content = {
        @Content(
            mediaType = "application/json",
            schema = @Schema(implementation = Pet.class),
            examples = @ExampleObject(
                name = "jsonPet",
                value = "{ \"id\": 1, \"name\": \"Fluffy\", \"status\": \"available\" }"
            )
        ),
        @Content(
            mediaType = "application/xml",
            schema = @Schema(implementation = Pet.class),
            examples = @ExampleObject(
                name = "xmlPet",
                value = "<pet><id>1</id><name>Fluffy</name><status>available</status></pet>"
            )
        ),
        @Content(
            mediaType = "text/plain",
            schema = @Schema(type = "string"),
            examples = @ExampleObject(
                name = "textPet",
                value = "Pet ID: 1, Name: Fluffy, Status: available"
            )
        )
    }
)

Response with Links

@PostMapping("/pets")
@ApiResponse(
    responseCode = "201",
    description = "Pet created successfully",
    headers = @Header(
        name = "Location",
        description = "URL of the newly created pet resource",
        schema = @Schema(type = "string", format = "uri")
    ),
    content = @Content(
        mediaType = "application/json",
        schema = @Schema(implementation = Pet.class)
    ),
    links = {
        @Link(
            name = "GetPetById",
            description = "Link to retrieve the created pet",
            operationId = "getPetById",
            parameters = @LinkParameter(
                name = "id",
                expression = "$response.body#/id"
            )
        ),
        @Link(
            name = "UpdatePet",
            description = "Link to update the created pet",
            operationId = "updatePet", 
            parameters = @LinkParameter(
                name = "id",
                expression = "$response.body#/id"
            )
        ),
        @Link(
            name = "DeletePet",
            description = "Link to delete the created pet",
            operationId = "deletePet",
            parameters = @LinkParameter(
                name = "id", 
                expression = "$response.body#/id"
            )
        )
    }
)

Conditional Response Documentation

@PutMapping("/pets/{id}")
@ApiResponse(
    responseCode = "200", 
    description = "Pet updated successfully",
    content = @Content(
        mediaType = "application/json",
        schema = @Schema(implementation = Pet.class)
    )
)
@ApiResponse(
    responseCode = "201",
    description = "Pet created (ID did not exist)",
    headers = @Header(
        name = "Location",
        description = "URL of the newly created pet",
        schema = @Schema(type = "string", format = "uri")
    ),
    content = @Content(
        mediaType = "application/json", 
        schema = @Schema(implementation = Pet.class)
    )
)
@ApiResponse(
    responseCode = "400",
    description = "Invalid request data",
    content = @Content(
        mediaType = "application/json",
        schema = @Schema(implementation = ValidationErrorResponse.class)
    )
)

Response with Custom Headers

@GetMapping("/pets")
@ApiResponse(
    responseCode = "200",
    description = "List of pets retrieved successfully",
    headers = {
        @Header(
            name = "X-Total-Count",
            description = "Total number of pets available",
            schema = @Schema(type = "integer", minimum = "0"),
            example = "150"
        ),
        @Header(
            name = "X-Page-Count", 
            description = "Total number of pages available",
            schema = @Schema(type = "integer", minimum = "1"),
            example = "8"
        ),
        @Header(
            name = "X-Per-Page",
            description = "Number of items per page",
            schema = @Schema(type = "integer", minimum = "1", maximum = "100"),
            example = "20"
        ),
        @Header(
            name = "X-Current-Page",
            description = "Current page number",
            schema = @Schema(type = "integer", minimum = "1"),
            example = "1"
        ),
        @Header(
            name = "Link",
            description = "Pagination links (RFC 5988)",
            schema = @Schema(type = "string"),
            example = "<https://api.petstore.io/pets?page=2>; rel=\"next\", <https://api.petstore.io/pets?page=8>; rel=\"last\""
        )
    },
    content = @Content(
        mediaType = "application/json",
        schema = @Schema(implementation = PetListResponse.class)
    )
)

ApiResponse Attributes

public @interface ApiResponse {
    String description() default "";
    String responseCode() default "default";
    Header[] headers() default {};
    Link[] links() default {};
    Content[] content() default {};
    Extension[] extensions() default {};
    String ref() default "";
    boolean useReturnTypeSchema() default false;
}

ApiResponses

Container annotation for multiple response scenarios, allowing comprehensive documentation of all possible operation outcomes.

Complete Response Documentation

@PostMapping("/pets")
@Operation(summary = "Create a new pet", tags = {"pets"})
@ApiResponses({
    @ApiResponse(
        responseCode = "201",
        description = "Pet created successfully", 
        headers = @Header(
            name = "Location",
            description = "URI of the created pet resource",
            schema = @Schema(type = "string", format = "uri")
        ),
        content = @Content(
            mediaType = "application/json",
            schema = @Schema(implementation = Pet.class),
            examples = @ExampleObject(
                name = "createdPet",
                summary = "Successfully created pet",
                value = """
                    {
                        "id": 124,
                        "name": "New Pet",
                        "category": {"id": 1, "name": "Dogs"},
                        "status": "available"
                    }
                    """
            )
        ),
        links = @Link(
            name = "GetCreatedPet",
            operationId = "getPetById",
            parameters = @LinkParameter(name = "id", expression = "$response.body#/id")
        )
    ),
    @ApiResponse(
        responseCode = "400",
        description = "Invalid input data provided",
        content = @Content(
            mediaType = "application/json",
            schema = @Schema(implementation = ValidationErrorResponse.class),
            examples = {
                @ExampleObject(
                    name = "missingRequiredFields",
                    summary = "Missing required fields",
                    description = "Error when required fields are not provided",
                    value = """
                        {
                            "error": "VALIDATION_ERROR",
                            "message": "Required fields are missing",
                            "violations": [
                                {
                                    "field": "name",
                                    "message": "Pet name is required"
                                },
                                {
                                    "field": "status", 
                                    "message": "Pet status must be specified"
                                }
                            ]
                        }
                        """
                ),
                @ExampleObject(
                    name = "invalidFieldValues",
                    summary = "Invalid field values",
                    description = "Error when field values don't meet constraints",
                    value = """
                        {
                            "error": "VALIDATION_ERROR",
                            "message": "Invalid field values provided",
                            "violations": [
                                {
                                    "field": "name",
                                    "message": "Pet name must be between 1 and 50 characters"
                                },
                                {
                                    "field": "status",
                                    "message": "Status must be one of: available, pending, sold"
                                }
                            ]
                        }
                        """
                )
            }
        )
    ),
    @ApiResponse(
        responseCode = "401",
        description = "Authentication required - Invalid or missing API key",
        headers = @Header(
            name = "WWW-Authenticate",
            description = "Authentication method required",
            schema = @Schema(type = "string", defaultValue = "ApiKey")
        ),
        content = @Content(
            mediaType = "application/json",
            schema = @Schema(implementation = ErrorResponse.class),
            examples = @ExampleObject(
                name = "authenticationError",
                value = """
                    {
                        "error": "AUTHENTICATION_REQUIRED",
                        "message": "Valid API key is required",
                        "code": 401
                    }
                    """
            )
        )
    ),
    @ApiResponse(
        responseCode = "403",
        description = "Insufficient permissions - User cannot create pets",
        content = @Content(
            mediaType = "application/json",
            schema = @Schema(implementation = ErrorResponse.class),
            examples = @ExampleObject(
                name = "permissionError",
                value = """
                    {
                        "error": "INSUFFICIENT_PERMISSIONS",
                        "message": "User does not have permission to create pets",
                        "requiredPermission": "pets:create",
                        "code": 403
                    }
                    """
            )
        )
    ),
    @ApiResponse(
        responseCode = "409",
        description = "Conflict - Pet with same name already exists",
        content = @Content(
            mediaType = "application/json",
            schema = @Schema(implementation = ConflictErrorResponse.class),
            examples = @ExampleObject(
                name = "conflictError",
                value = """
                    {
                        "error": "RESOURCE_CONFLICT",
                        "message": "A pet with this name already exists",
                        "conflictField": "name",
                        "conflictValue": "Fluffy",
                        "existingResourceId": 123,
                        "code": 409
                    }
                    """
            )
        )
    ),
    @ApiResponse(
        responseCode = "422",
        description = "Unprocessable Entity - Request data fails business rules",
        content = @Content(
            mediaType = "application/json",
            schema = @Schema(implementation = BusinessRuleErrorResponse.class),
            examples = @ExampleObject(
                name = "businessRuleError",
                value = """
                    {
                        "error": "BUSINESS_RULE_VIOLATION",
                        "message": "Cannot create pet: Maximum pet limit reached for this user",
                        "rule": "MAX_PETS_PER_USER",
                        "limit": 10,
                        "current": 10,
                        "code": 422
                    }
                    """
            )
        )
    ),
    @ApiResponse(
        responseCode = "429",
        description = "Too Many Requests - Rate limit exceeded",
        headers = {
            @Header(
                name = "X-Rate-Limit-Limit",
                description = "Request limit per time window",
                schema = @Schema(type = "integer")
            ),
            @Header(
                name = "X-Rate-Limit-Remaining", 
                description = "Remaining requests in current window",
                schema = @Schema(type = "integer")
            ),
            @Header(
                name = "X-Rate-Limit-Reset",
                description = "Time when rate limit resets",
                schema = @Schema(type = "integer", format = "int64")
            ),
            @Header(
                name = "Retry-After",
                description = "Seconds to wait before retrying",
                schema = @Schema(type = "integer")
            )
        },
        content = @Content(
            mediaType = "application/json",
            schema = @Schema(implementation = RateLimitErrorResponse.class),
            examples = @ExampleObject(
                name = "rateLimitError",
                value = """
                    {
                        "error": "RATE_LIMIT_EXCEEDED",
                        "message": "Too many requests. Rate limit exceeded.",
                        "retryAfter": 60,
                        "code": 429
                    }
                    """
            )
        )
    ),
    @ApiResponse(
        responseCode = "500",
        description = "Internal Server Error - Unexpected server error occurred",
        content = @Content(
            mediaType = "application/json",
            schema = @Schema(implementation = ErrorResponse.class),
            examples = @ExampleObject(
                name = "serverError",
                value = """
                    {
                        "error": "INTERNAL_SERVER_ERROR",
                        "message": "An unexpected error occurred while processing the request",
                        "traceId": "abc123def456",
                        "code": 500
                    }
                    """
            )
        )
    )
})
public ResponseEntity<Pet> createPet(@Valid @RequestBody CreatePetRequest request) {
    Pet createdPet = petService.create(request);
    URI location = ServletUriComponentsBuilder
        .fromCurrentRequest()
        .path("/{id}")
        .buildAndExpand(createdPet.getId())
        .toUri();
    
    return ResponseEntity.created(location).body(createdPet);
}

Async Operation Responses

@PostMapping("/pets/{id}/process")
@ApiResponses({
    @ApiResponse(
        responseCode = "202",
        description = "Processing started - Operation accepted for asynchronous processing",
        headers = {
            @Header(
                name = "Location",
                description = "URL to check processing status",
                schema = @Schema(type = "string", format = "uri")
            ),
            @Header(
                name = "X-Process-ID",
                description = "Unique identifier for the processing job",
                schema = @Schema(type = "string", format = "uuid")
            )
        },
        content = @Content(
            mediaType = "application/json",
            schema = @Schema(implementation = ProcessingResponse.class),
            examples = @ExampleObject(
                name = "processingStarted",
                value = """
                    {
                        "processId": "123e4567-e89b-12d3-a456-426614174000",
                        "status": "processing",
                        "message": "Pet processing has been started",
                        "estimatedCompletion": "2024-01-15T10:30:00Z",
                        "statusUrl": "/api/v1/processes/123e4567-e89b-12d3-a456-426614174000"
                    }
                    """
            )
        ),
        links = {
            @Link(
                name = "CheckStatus",
                description = "Check processing status",
                operationId = "getProcessStatus",
                parameters = @LinkParameter(
                    name = "processId",
                    expression = "$response.body#/processId"
                )
            ),
            @Link(
                name = "CancelProcess",
                description = "Cancel the processing job",
                operationId = "cancelProcess",
                parameters = @LinkParameter(
                    name = "processId",
                    expression = "$response.body#/processId"
                )
            )
        }
    ),
    @ApiResponse(
        responseCode = "303",
        description = "See Other - Processing already completed, redirect to result",
        headers = @Header(
            name = "Location",
            description = "URL of the completed processing result",
            schema = @Schema(type = "string", format = "uri")
        )
    )
})

Bulk Operation Responses

@PostMapping("/pets/bulk")
@ApiResponses({
    @ApiResponse(
        responseCode = "207",
        description = "Multi-Status - Partial success with mixed results",
        content = @Content(
            mediaType = "application/json",
            schema = @Schema(implementation = BulkOperationResponse.class),
            examples = @ExampleObject(
                name = "partialSuccess",
                summary = "Partial success example",
                description = "Some pets created successfully, others failed",
                value = """
                    {
                        "overallStatus": "partial_success",
                        "totalRequests": 5,
                        "successCount": 3,
                        "failureCount": 2,
                        "results": [
                            {
                                "index": 0,
                                "status": 201,
                                "success": true,
                                "data": {"id": 101, "name": "Pet1", "status": "available"}
                            },
                            {
                                "index": 1,
                                "status": 400,
                                "success": false,
                                "error": {"message": "Invalid pet name", "field": "name"}
                            },
                            {
                                "index": 2,
                                "status": 201,
                                "success": true,
                                "data": {"id": 102, "name": "Pet2", "status": "available"}
                            },
                            {
                                "index": 3,
                                "status": 409,
                                "success": false,
                                "error": {"message": "Pet name already exists", "conflictField": "name"}
                            },
                            {
                                "index": 4,
                                "status": 201,
                                "success": true,
                                "data": {"id": 103, "name": "Pet3", "status": "available"}
                            }
                        ]
                    }
                    """
            )
        )
    ),
    @ApiResponse(
        responseCode = "200",
        description = "All operations completed successfully",
        content = @Content(
            mediaType = "application/json",
            schema = @Schema(implementation = BulkOperationResponse.class)
        )
    ),
    @ApiResponse(
        responseCode = "400",
        description = "All operations failed due to invalid input",
        content = @Content(
            mediaType = "application/json",
            schema = @Schema(implementation = BulkOperationResponse.class)
        )
    )
})

File Download Responses

@GetMapping("/pets/{id}/photo")
@ApiResponses({
    @ApiResponse(
        responseCode = "200",
        description = "Pet photo download",
        headers = {
            @Header(
                name = "Content-Type",
                description = "Image media type",
                schema = @Schema(type = "string", allowableValues = {"image/jpeg", "image/png", "image/gif"})
            ),
            @Header(
                name = "Content-Length",
                description = "File size in bytes",
                schema = @Schema(type = "integer", minimum = "0")
            ),
            @Header(
                name = "Content-Disposition",
                description = "File download disposition",
                schema = @Schema(type = "string"),
                example = "attachment; filename=\"pet-123-photo.jpg\""
            ),
            @Header(
                name = "Cache-Control",
                description = "Cache control directives",
                schema = @Schema(type = "string"),
                example = "public, max-age=3600"
            ),
            @Header(
                name = "ETag",
                description = "Entity tag for caching",
                schema = @Schema(type = "string"),
                example = "\"abc123def456\""
            ),
            @Header(
                name = "Last-Modified",
                description = "Last modification date",
                schema = @Schema(type = "string", format = "date-time")
            )
        },
        content = {
            @Content(mediaType = "image/jpeg", schema = @Schema(type = "string", format = "binary")),
            @Content(mediaType = "image/png", schema = @Schema(type = "string", format = "binary")),
            @Content(mediaType = "image/gif", schema = @Schema(type = "string", format = "binary"))
        }
    ),
    @ApiResponse(
        responseCode = "304",
        description = "Not Modified - Photo has not changed since last request",
        headers = {
            @Header(
                name = "Cache-Control",
                schema = @Schema(type = "string")
            ),
            @Header(
                name = "ETag", 
                schema = @Schema(type = "string")
            )
        }
    ),
    @ApiResponse(
        responseCode = "404",
        description = "Photo not found for this pet"
    )
})

ApiResponses Attributes

public @interface ApiResponses {
    ApiResponse[] value() default {};
}

Response Model Examples

Error Response Models

@Schema(description = "Standard error response")
public class ErrorResponse {
    @Schema(description = "Error code identifier", example = "RESOURCE_NOT_FOUND")
    private String error;
    
    @Schema(description = "Human-readable error message", example = "The requested resource was not found")
    private String message;
    
    @Schema(description = "HTTP status code", example = "404")
    private Integer code;
    
    @Schema(description = "Request trace ID for debugging", example = "abc123def456")
    private String traceId;
    
    @Schema(description = "Timestamp of the error", format = "date-time")
    private Instant timestamp;
}

@Schema(description = "Validation error response with field-level details")
public class ValidationErrorResponse extends ErrorResponse {
    @Schema(description = "List of field validation violations")
    private List<FieldViolation> violations;
    
    @Schema(description = "Field validation violation details")
    public static class FieldViolation {
        @Schema(description = "Field name that failed validation", example = "name")
        private String field;
        
        @Schema(description = "Validation failure message", example = "must not be blank")
        private String message;
        
        @Schema(description = "Rejected value", example = "")
        private Object rejectedValue;
    }
}

Install with Tessl CLI

npx tessl i tessl/maven-io-swagger-core-v3--swagger-annotations

docs

advanced-features.md

core-annotations.md

index.md

responses.md

schema-media.md

security.md

servers-tags.md

tile.json