Schema-annotation: add property `addJavaDoc`
Currently, I need to duplicate existing Javadoc from the property into the Schema.description tag. This is very annoying and hurts DRY (don’t repeat yourself). It fills the Java class with redundant data and is worse for maintenance, etc..:
/**
* The description.
*
* <p>
* Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy
* eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
* voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
*/
@Schema(readOnly = true, addJavaDoc=true, description = "The description. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy\n"
+ " * eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam\n"
+ " * voluptua. At vero eos et accusam et justo duo dolores et ea rebum.")
private final String description;
Please add a new property for the Schema-Tag, e.g. addJavaDoc = true | false. If the value is set to true, the Javadoc is appended to the OpenAPI description value:
For example:
/**
* The description.
*
* <p>
* Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy
* eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
* voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
*/
@Schema(readOnly = true, addJavaDoc=true)
private final String description;
another example using both addJavaDoc and an explicit description that simply appends the Javadoc after the description value (in this case: "My description. The description page..."):
/**
* The description.
*
* <p>
* Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy
* eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam
* voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
*/
@Schema(readOnly = true, addJavaDoc=true, description="My description")
private final String description;
The Javadoc can contain html-tags or Markdown-Syntax (https://openjdk.org/jeps/467) which needs to be considered when putting this in the openapi description value.
In my company, we check with CheckStyle that methods have full Javadoc.
However, when a method is well documented with OpenAPI, that's not necessary (DRY, as you stated).
So we just annotate the following:
@SuppressWarnings("javadoc") // Documented with OpenAPI
@SuppressWarnings("javadoc") // Documented with OpenAPI
This is really a bad workaround. What about the Javadoc for such properites/getters/setters -you don't have one.
I'm pretty sure this issue has been raised before. The main problem is that when scanning annotations, the source code (and JavaDoc comments) are no longer available. There might be a way to do this in the Maven plugin where the comments are preprocessed, but I haven't seen any obvious solution yet.
We don't document private properties, we document getters and setters, since they are public.
The main problem is that when scanning annotations, the source code (and JavaDoc comments) are no longer available.
It is a pity, I don't know much about it, I thought it would be possible somehow with an annotation preprocessor. After all, smallrye has access to the classes and the code.
There might be a way to do this in the Maven plugin where the comments are preprocessed, but I haven't seen any obvious solution yet.
This would be a valuable solution. Imagine a Smallrye annotation preprocessor on which compilation (the generation of openapi.yml) is done where it has access to the source code (similar to the preprocessing of JBoss Message Logger, Hibernate Criteria Builder or Jakarta Data, which also creates some files (in this case Java files) live within target/generated/sources-package).
I think when generating from Java to OpenAPI such important things (like setting the description via JavaDoc) should be taken into account.
Other possible solutions:
-
using
javaparser-libwithJavadocDocument(see https://dzone.com/articles/extracting-javadoc-documentation-from-source-files and https://github.com/javaparser/javaparser/issues/433) -
using the official
Doclet-API (jdk.javadoc.doclet.Doclet with https://docs.oracle.com/en/java/javase/23/docs/api/jdk.compiler/com/sun/source/doctree/DocTree.html which includes an API for writing customdoclets(maybe there is a way to parse it as ajsonorymland merge it back toopenapi.yml)
There might be a way to do this in the Maven plugin where the comments are preprocessed, but I haven't seen any obvious solution yet.
This would be a valuable solution. Imagine a
Smallrye annotation preprocessoron which compilation (the generation ofopenapi.yml) is done where it has access to the source code (similar to the preprocessing ofJBoss Message Logger,Hibernate Criteria BuilderorJakarta Data, which also creates some files (in this case Java files) live withintarget/generated/sources-package).I think when generating from Java to OpenAPI such important things (like setting the
descriptionviaJavaDoc) should be taken into account.
Yes, it seems feasible [1] using an annotation processor, or the Maven process-sources or generate-resources phase.
[1] https://docs.oracle.com/en/java/javase/17/docs/api/java.compiler/javax/lang/model/util/Elements.html#getDocComment(javax.lang.model.element.Element)
@MikeEdgar It would be great to have something like that. Can you do it?
@nimo23 I won't have the time for it anytime soon due to competing priorities. We always welcome contributions from the community if you have the spare cycles to give it a try.
We always welcome contributions from the community if you have the spare cycles to give it a try.
I already tried and played with javax.lang.model.element.ElementVisitor and ElementFilter. A not working example:
public static void printJavadocsForClass(Class<?> clazz, String fieldName) {
// TODO: consider all members (not only fields)
var fields = clazz.getDeclaredFields();
var fieldList = Arrays.asList(fields);
var elements = ElementFilter.fieldsIn(fieldList);
// this is not working: cannot find connection between Field and Element
var elements = ElementFilter.fieldsIn(clazz.getDeclaredFields());
TypeElement element = elements.getTypeElement(clazz.getName());
var allMembers = Elements.getAllMembers(element);
var elements = ElementFilter.fieldsIn(Elements.getAllMembers(clazz));
for (Element element : elements) {
if (element.toString().equals(fieldName)) {
return elements.getDocComment(element);
}
}
return null;
}
But unfortunately I don't know anything about all these APIs and don't know the subtle connections between these APIs (e.g. Element<->Field) and Smallrye (compilation, process-sources, etc.) in order to be able to provide useful results here. I have to wait until someone with relevant experience has time for this issue.