Understanding MicroProfile OpenAPI Specification 3.0

This article explains the MicroProfile OpenAPI 3.0 specification, covering its architecture, configuration options, core properties, annotation usage, server definitions, programming model, model readers, filters, processing rules, endpoint behavior, and release notes for both 3.0 and earlier versions.

JakartaEE China Community
JakartaEE China Community
JakartaEE China Community
Understanding MicroProfile OpenAPI Specification 3.0

Overview

MicroProfile OpenAPI 1.0 defines Java interfaces and a programming model that generate OpenAPI v3 documentation directly from JAX‑RS applications. The specification relies on MicroProfile Config for all configuration values.

Core Configuration Properties

mp.openapi.model.reader

– Fully qualified class name of an OASModelReader implementation. mp.openapi.filter – Fully qualified class name of an OASFilter implementation. mp.openapi.scan.disable – Boolean flag to disable annotation scanning (default false). mp.openapi.scan.packages – Comma‑separated list of packages to scan (e.g., mp.openapi.scan.packages=com.xyz.A,com.xyz.B). mp.openapi.scan.classes – Comma‑separated list of classes to scan. mp.openapi.scan.exclude.packages – Packages to exclude from scanning. mp.openapi.scan.exclude.classes – Classes to exclude from scanning. mp.openapi.servers – Global server list (e.g.,

mp.openapi.servers=https://api.example.com/v1,https://backup.example.com/v1

). mp.openapi.servers.path. – Prefix for path‑specific server overrides. mp.openapi.servers.operation. – Prefix for operation‑specific server overrides (requires an operationId). mp.openapi.schema. – JSON‑encoded schema definitions for specific classes when source code is unavailable.

Example Schema Configuration

mp.openapi.schema.java.util.Date = {</code>
<code>  "name": "EpochMillis",</code>
<code>  "type": "number",</code>
<code>  "format": "int64",</code>
<code>  "description": "Milliseconds since 1970‑01‑01T00:00:00Z"</code>
<code>}

Documentation Mechanisms

Enhance JAX‑RS annotations with OpenAPI annotations.

Start from the initial /openapi output and augment it with static OpenAPI files (contract‑first).

Provide a programmatic model tree via the programming model.

Apply filters after the document is built to modify or remove elements.

Annotation Priority

If the same annotation appears on both a class and a method, the method value overrides the class value (common for @Server and @Tag). For @Parameter and @RequestBody, method‑parameter annotations override method‑level annotations; mixing them is discouraged.

Key Annotation Examples

Operation with Summary

@GET</code>
<code>@Path("/findByStatus")</code>
<code>@Operation(summary = "Finds Pets by status", description = "Multiple status values can be provided with comma‑separated strings")</code>
<code>public Response findPetsByStatus(...){ ... }

Resulting fragment:

/pet/findByStatus:</code>
<code>  get:</code>
<code>    summary: Finds Pets by status</code>
<code>    description: Multiple status values can be provided with comma separated strings</code>
<code>    operationId: findPetsByStatus

Operation with Multiple Responses

@GET</code>
<code>@Path("/{username}")</code>
<code>@Operation(summary = "Get user by user name")</code>
<code>@APIResponse(description = "The user", content = @Content(mediaType = "application/json", schema = @Schema(implementation = User.class)))</code>
<code>@APIResponse(responseCode = "400", description = "User not found")</code>
<code>public Response getUserByName(@Parameter(description = "The name that needs to be fetched. Use user1 for testing.", required = true) @PathParam("username") String username){...}
/user/{username}:</code>
<code>  get:</code>
<code>    summary: Get user by user name</code>
<code>    operationId: getUserByName</code>
<code>    parameters:</code>
<code>      - name: username</code>
<code>        in: path</code>
<code>        description: "The name that needs to be fetched. Use user1 for testing."
<code>        required: true</code>
<code>        schema:</code>
<code>          type: string</code>
<code>    responses:</code>
<code>      default:</code>
<code>        description: The user</code>
<code>        content:</code>
<code>          application/json:</code>
<code>            schema:</code>
<code>              $ref: '#/components/schemas/User'</code>
<code>      400:</code>
<code>        description: User not found

Request Body Example

@POST</code>
<code>@Path("/user")</code>
<code>@Operation(summary = "Create user", description = "This can only be done by the logged in user.")</code>
<code>public Response createUser(@RequestBody(description = "Created user object", required = true, content = @Content(schema = @Schema(implementation = User.class))) User user, @QueryParam("name") String name, @QueryParam("code") String code){ ... }
post:</code>
<code>  summary: Create user</code>
<code>  description: This can only be done by the logged in user.</code>
<code>  operationId: createUser</code>
<code>  parameters:</code>
<code>    - name: name</code>
<code>      in: query</code>
<code>      schema:</code>
<code>        type: string</code>
<code>    - name: code</code>
<code>      in: query</code>
<code>      schema:</code>
<code>        type: string</code>
<code>  requestBody:</code>
<code>    description: Created user object</code>
<code>    content:</code>
<code>      '*/*':</code>
<code>        schema:</code>
<code>          $ref: '#/components/schemas/User'</code>
<code>        required: true</code>
<code>  responses:</code>
<code>    default:</code>
<code>      description: no description

Server Definition Precedence

Servers can be defined globally, per‑path, or per‑operation. Method‑level @Server entries override class‑level entries, which in turn override definition‑level entries.

@OpenAPIDefinition(servers = { @Server(description = "definition server", url = "http://{var1}.def/{var2}", variables = { @ServerVariable(name = "var1", defaultValue = "1", enumeration = {"1","2"}), @ServerVariable(name = "var2", defaultValue = "1", enumeration = {"1","2"}) }) })</code>
<code>@Server(description = "class server", url = "http://{var1}.class/{var2}")</code>
<code>public class ServersResource {</code>
<code>  @GET @Path("/")</code>
<code>  @Server(description = "method server", url = "http://{var1}.method")</code>
<code>  public Response get(){ return Response.ok("ok").build(); }</code>
<code>}
openapi: 3.0.2</code>
<code>servers:</code>
<code>- url: http://{var1}.def/{var2}</code>
<code>  description: definition server</code>
<code>paths:</code>
<code>  /:</code>
<code>    get:</code>
<code>      operationId: get</code>
<code>      servers:</code>
<code>        - url: http://{var1}.class/{var2}</code>
<code>          description: class server</code>
<code>        - url: http://{var1}.method</code>
<code>          description: method server

Programming Model

Model objects are created via OASFactory in the org.eclipse.microprofile.openapi.models package.

OASFactory.createObject(Info.class)</code>
<code>    .title("Airlines")</code>
<code>    .description("Airlines APIs")</code>
<code>    .version("1.0.0");

OASModelReader

Implement OASModelReader to supply a complete or partial OpenAPI model tree. Register it with mp.openapi.model.reader (e.g., mp.openapi.model.reader=com.mypkg.MyReader). If a full model is supplied, set mp.openapi.scan.disable=true to skip annotation scanning.

OASFilter

Implement OASFilter to receive callbacks for each OpenAPI element and modify or remove them. Register with mp.openapi.filter (e.g., mp.openapi.filter=com.mypkg.MyFilter). Child elements are processed before their parents; filterOpenAPI is called last.

Processing Rules

Read configuration values from the mp.openapi namespace.

Invoke the registered OASModelReader (if any).

Load a static OpenAPI file from the application’s META-INF directory (named openapi.yml, openapi.yaml or openapi.json).

Process JAX‑RS and OpenAPI annotations unless scanning is disabled.

Apply all registered OASFilter implementations.

The later steps override values from earlier steps.

OpenAPI Endpoint

The fully processed document is exposed at the root URL /openapi via HTTP GET. The default response format is YAML; if the request contains Accept: application/json, the implementation must return JSON with Content‑Type: application/json. Implementations may optionally support a format query parameter to switch between YAML and JSON.

Root Prefix Handling

If an application is deployed under a root prefix (e.g., /myApp), server URLs must include that prefix or the corresponding proxy URL.

Multiple Applications

When a MicroProfile runtime hosts multiple applications, the /openapi endpoint should return the logical union of all generated OpenAPI documents, handling ID conflicts and ensuring unique naming.

Integration with Other MicroProfile Specs

Interfaces annotated with @RegisterRestClient are excluded from the generated OpenAPI document, preventing internal client contracts from leaking into the public API description.

Release Notes – MicroProfile OpenAPI 3.0

API/SPI Changes

Model interfaces no longer extend Map; explicit methods are provided for Scopes, ServerVariables, APIResponses, Callback, Content, Path, SecurityRequirement, Server, PathItem, and Schema.

New annotations: @SchemaProperty, @RequestBodySchema, @APIResponseSchema.

Configuration property mp.openapi.schema.* allows defining schemas for classes without source code.

Feature Changes

Getter methods now return copies of internal collections; setters must not store the passed collection directly, improving immutability and thread safety.

Other Changes

JavaDoc updated, TCK enhanced to verify new behavior, numerous minor bug fixes and documentation improvements.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

JavaconfigurationAPI documentationAnnotationsOpenAPIJAX-RSMicroProfile
JakartaEE China Community
Written by

JakartaEE China Community

JakartaEE China Community, official website: jakarta.ee/zh/community/china; gitee.com/jakarta-ee-china; space.bilibili.com/518946941; reply "Join group" to get QR code

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.