I'm using Swagger with Jersey (JAX-RS) to serve API documentation. I configure Swagger like this:
ResourceConfig swaggerResourceConfig = new ResourceConfig()
.packages("io.swagger.v3.jaxrs2.integration.resources")
.register(OpenApiResource.class)
.register(SwaggerSerializers.class)
.register(AcceptHeaderOpenApiResource.class)
.property("jersey.config.server.wadl.disableWadl", true);
SwaggerConfiguration oasConfig = new SwaggerConfiguration()
.openApi(baseModel) // <-- I would want to serve the modified object, but can't at this point
.prettyPrint(true)
.resourcePackages(Set.of("my.api.package"));
OpenApiContext openApiCtx = new JaxrsOpenApiContextBuilder()
.openApiConfiguration(oasConfig)
.buildContext(true);
I have many endpoints where the ApiResponse.description is never set, so Swagger-UI shows errors: Structural error at {PATH} should have required property 'description' missingProperty: description
. I wrote a helper function that traverses the generated OpenAPI model and fills in empty descriptions, which I tested out and it works:
public OpenAPI patchMissingDescriptions(OpenAPI openAPI) {
if (openAPI.getPaths() != null) {
for (Entry<String, PathItem> entry : openAPI.getPaths().entrySet()) {
for (Operation operation : entry.getValue().readOperations()) {
if (operation.getResponses() != null) {
for (Entry<String, ApiResponse> respEntry : operation.getResponses().entrySet()) {
ApiResponse response = respEntry.getValue();
if (response.getDescription() == null) {
response.setDescription("some description");
}
}
}
}
}
}
return openAPI;
}
Problem:
atchMissingDescriptions()
after the OpenAPI
model is built but before Jersey serves the JSON/YAML docs.read()
on the OpenApiContext
to obtain the OpenAPI
is prohibitively slow due to deep reflection so I can't use this.What I'm looking for
An extension point in Swagger-Core or JAX-RS integration that lets me mutate the in-memory OpenAPI object exactly once, after it’s built but before it’s cached/serialized.
Or a recommended best practice / pattern for filling in default values, especially response descriptions without duplicating the scanning logic.
what I've tried:
What I needed to do was:
SwaggerConfiguration oasConfig = new SwaggerConfiguration()
.openApi(baseModel)
.readerClass(MyCustomReader.class.getName()) // <- HERE
.prettyPrint(true)
.resourcePackages(Set.of("my.api.package"));
io.swagger.v3.jaxrs2.Reader;
and overriding the read
methodpublic class MyCustomReader extends Reader {
@Override
public OpenAPI read(Class<?> cls,
String parentPath,
String parentMethod,
boolean isSubresource,
RequestBody parentRequestBody,
ApiResponses apiResponses,
Set<String> parentTags,
List<Parameter> parentParameters,
Set<Class<?>> scannedResources)
{
OpenAPI openAPI = super.read(cls, parentPath, parentMethod, isSubresource, parentRequestBody, apiResponses,
parentTags, parentParameters, scannedResources);
return populateMissingDescriptions(openAPI);
}
public static OpenAPI populateMissingDescriptions(OpenAPI openAPI) {
if (openAPI.getPaths() != null) {
for (Entry<String, PathItem> entry : openAPI.getPaths().entrySet()) {
String path = entry.getKey();
PathItem pathItem = entry.getValue();
for (Operation operation : pathItem.readOperations()) {
if (operation.getResponses() != null) {
for (Entry<String, ApiResponse> e : operation.getResponses().entrySet()) {
String status = e.getKey();
ApiResponse response = e.getValue();
if (response.getDescription() == null) {
response.setDescription("");
}
}
}
}
}
}
return openAPI;
}
}