Search code examples
swaggerjax-rsopenapimicroprofilesmallrye

Generate OpenAPI descriptions from JavaDoc


I have an application which provides an API with JAX-RS (Java API for RESTful Web Services / JSR-311).

For documentation purposes I provide an URL according to the OpenAPI-Specification, which is generated by Eclipse MicroProfile OpenAPI.

Everything is working fine, except the descriptions of the methods and parameters, which I need to add twice - in annotations and in JavaDoc:

/**
 * Finds all resources with the given prefix.
 *
 * @param prefix
 *            the prefix of the resource
 * @return the resources that start with the prefix
 */
@GET
@Path("/find/{prefix}")
@Produces(MediaType.APPLICATION_JSON)
@Operation(description = "Finds all resources with the given prefix")
public List<Resource> find(
        @Parameter(description = "The prefix of the resource") 
        @PathParam("prefix") final String prefix) {
    ...
}

I know that no runtime library can read the JavaDoc (because it is not part of the class files), which is the main reason for the annotations. But I wonder if there is some other option for one of the OpenAPI generation tools (Swagger, Eclipse MicroProfile OpenAPI, ...), which prevents me from manually syncing the documentation?

In another project for example I'm using a doclet which serializes the JavaDoc and stores it in the class path, to present an Beans API documentation to the user at runtime. But even if I make use of this doclet here, I see no option to provide that JavaDoc descriptions to the OpenAPI libraries during runtime.

I know that I could drop the JavaDoc, if the users of my API use only "foreign languages", as they wouldn't see the JavaDoc anyway. But what happens if the other side of the API is a JAX-RS client? In that case the JavaDoc would be a huge support.


Solution

  • I got it running with Eclipse Microprofile OpenAPI.

    I had to define my own OASFilter:

    public class JavadocOASDescriptionFilter implements OASFilter {
    
        @Override
        public void filterOpenAPI(final OpenAPI openAPI) {
            openAPI.getComponents().getSchemas().forEach(this::initializeSchema);
            openAPI.getPaths().forEach(this::initializePathItem);
        }
    
        private void initializeSchema(final String name, final Schema schema) {
            final SerializedJavadoc javadoc = findJavadocForSchema(name);
            if (StringUtils.isEmpty(schema.getDescription())) {
                schema.setDescription(javadoc.getTypeComment());
            }
            if (schema.getProperties() != null) {
                schema.getProperties().forEach((property, propertySchema) -> {
                    if (StringUtils.isEmpty(propertySchema.getDescription())) {
                        propertySchema.setDescription(javadoc.getAttributeComments().get(property));
                    }
                });
            }
        }
        ...
    }
    

    Then I had to declare that filter in META-INF/microprofile-config.properties:

    mp.openapi.filter=mypackage.JavadocOASDescriptionReader
    

    See here for the discussion on this topic: https://github.com/eclipse/microprofile-open-api/issues/485