Clarify meaning of default value for java annotation properties
See original GitHub issueCurrently this specification includes a set of Java annotations that developers can use to further document their JAX-RS APIs directly in code. All of these annotations have properties (that typically correspond closely with OpenAPI properties) with default values. For example:
@Target({ ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Inherited
public @interface Operation {
/**
* Provides a brief description of what this operation does.
*
* @return a summary of this operation
**/
String summary() default "";
/**
* A verbose description of the operation behaviour.
* CommonMark syntax MAY be used for rich text representation.
*
* @return a description of this operation
**/
String description() default "";
/**
* Unique string used to identify the operation.
* The id MUST be unique among all operations described in the API.
* <p>
* Tools and libraries MAY use the operationId to uniquely identify an operation,
* therefore, it is RECOMMENDED to follow common programming naming conventions.
* </p>
* @return the ID of this operation
**/
String operationId() default "";
Every annotation property has a default value so that developers can pick and choose which properties they wish to include when they apply the operation in their code. For example, when applying the above Operation
annotation, the developer can provide a summary
without being required to also provide a description
and operationId
:
@Operation(
summary = "Get Example"
)
@GET
@Path("/example")
public String getExample();
The Microprofile OpenAPI implementation’s annotation scanner is responsible for turning all of these annotations into a generated OpenAPI document.
The default values for all properties in all MP+OAI annotations are meant to indicate to the annotation scanner that the developer did not include that property in their application of the annotation. The default values are NOT meant to indicate what value the property will have in the generated OpenAPI document.
For the example above, this is what the OpenAPI annotation scanner might generate:
{
"openapi": "3.0.2",
"paths": {
"/example": {
"get": {
"summary": "Get Example",
"responses": {
"200": {
"content": {
"application/json": {
"schema": {
"type": "string"
}
}
}
}
}
}
}
}
Notice that no operationId
is included, and no description
is included in the output, despite the @Operation
annotation being applied. That annotation has both operationId
and description
properties with default value of empty string. Nevertheless, the annotation processor did not generate those properties in the output document. Again, the reason for this is that the default values for annotation properties are intended to signal to the annotation processor that the developer did not include the property when they added the annotation to their code, so the annotation processor should do whatever is appropriate for that property. In most cases, the appropriate thing is to omit the property from the output.
For some properties this behavior is sensible, but for others it is more confusing. However, because there is no way, in Java, to set the default value of an annotation property to null, it’s the best we’ve got.
So to clarify the behavior of these annotations, we should consider updating the javadoc for at least the annotation properties with confusing default values. This is a rather subjective task, so I think we can start by enumerating which of the properties might be confusing by listing them in comments to this issue.
Issue Analytics
- State:
- Created 4 years ago
- Comments:9 (5 by maintainers)
Top GitHub Comments
This has been a very interesting discussion, and also relates to the discussion about request bodies here: https://github.com/eclipse/microprofile-open-api/issues/349
We discussed this again during today’s hangout and have reached some conclusions.
The first is that after considering all the points that have been made, we still think that the current way annotation property defaults are treated is appropriate and the least evil of the options we have. So we’re going to continue with the approach that default values for the MP+OAI annotation properties should be treated (by implementations) as though the property was not specified by the developer. This is not perfect but we think it’s the best developer experience.
However, we can (and will) make some changes to make things clearer for both implementer and users of the spec. Things we are going to change/add:
Now, typically the default values for annotation properties should match (as closely as possible) the default value for that property in the upstream OpenAPI specification. This should cut down on some confusion, but is not always possible and more confusingly is not always desirable. Because the annotation scanner in Microprofile+OpenAPI is targeting JAX-RS, we feel that default scanning behavior should accurately reflect the characteristics of JAX-RS rather than the default values of OpenAPI. So in some exceptional cases, the default value for certain annotation properties may differ from the upstream specification default so that the default behavior of the annotation scanner more closely models the actual behavior of the application.
The current example of this is https://github.com/eclipse/microprofile-open-api/issues/349, where we will be changing the default value of
required
for request bodies because request bodies are by default required by JAX-RS. In these exceptional cases, we will be documenting the reason why we are diverging from the typical behavior in two places:Hopefully this is a rational choice we are making, given the lack of completely ideal choices. If Java would only allow
null
as a default value for an annotation property, things would be much easier!This may be a silly idea, but would it make sense to do something like this:
The generator should substitute
"__method_name__"
with name of the resource method name.For extra points, let a new OpenApi flag control whether to default substitution to empty string (as it happens today), or resource method name.
This would allow generation of richer APIs without having to annotate all methods, as we have to do today. Which is a pain.