OpenAPI: Java controller methods with identical URL paths but different HTTP signatures #343
-
When generating the OpenAPI definition, Java controller methods with identical URL paths, but distinct HTTP signatures, are merged to create a single operation in the definition. This approach is leading to two unintended consequences. The first consequence is that the operation ID can be frightfully long and misleading. The following is an example of an operation ID generated from the merging of controller methods:
The above is incomprehensible and it's made worse from the fact that code generators derive the client method and model names from the operation IDs. As a side note, some code generators like the R one choke because the generated model filename is too long for the filesystem. The second consequence to the merging of controller methods is that the each method's HTTP signature (e.g., query params) is decontextualised in the API definition: the consumer can't know from the definition which combination of HTTP parameters is correct. Say query param a is required in controller method x and query param b is required in controller method y. Both query params will be described in the OpenAPI operation xy. However, what should be described in operation xy? That both query params are required? This would be incorrect but even describing both parameters as optional is incorrect. Having said this, the latter could be more acceptable. OpenAPI's notion of an operation doesn't align neatly with the DHIS2 one but we could workaround this mismatch as proposed in an OpenAPI discussion. Alternatively, we could accept the fact that OpenAPI operations can lose context though doing so means that consumers need to refer to the documentation, if it exists, to understand how to call an operation. Additionally, without the workaround, we still need to address the problem where we have unwieldy operation names. I'm reluctant to suggest creating yet another OpenAPI annotation since it will be hard for developers to know when it should be applied. Perhaps we can throw an error while generating the OpenAPI definition if there are multiple controller methods that need to be merged but the developer hasn't added an annotation customising the operation ID. Such an error would then be caught while running the tests. |
Beta Was this translation helpful? Give feedback.
Replies: 2 comments
-
OperationIdThe only requirement thus far for the Merge vs. Path with Query ParametersI think we have cases which we want to merge and others we want to make into a unique path with specific parameters. Merge would be virtually same input different output format, like methods that generate JSON, CSV and XML. These still are "the same" operation in OpenAPI terms which generates responses with different media types. Yet, we cannot always guarantee their parameters are actually identical. This is where we would need to find ways to improve a merge, e.g. by adding a description to the parameters that are exclusive for a media type output. The special path including query parameters on the other hand is well suited for methods of equal path where the clashing methods do have each their set of special parameters that the others do not have. The idea would be to identify those parameters and add them to the path? How does this work exactly? Are only required parameters relevant? When/where would this be identified? We could just adjust the merge and have it either merge or adjust by updating the OpenAPI path of the operation so it includes the special parameters. This part needs more detailing on how it is solved with some examples and how they would be transformed. |
Beta Was this translation helpful? Give feedback.
-
We had a huddle discussion on this, quick summary:
Pointers
|
Beta Was this translation helpful? Give feedback.
We had a huddle discussion on this, quick summary:
Endpoint
object is scarpedEndpoint
for a path, the paths are made unique by putting theEndpoint
under a new path in theapi.getEndpoints()
map where each gets theirEndpoint.name
appended after the#
. For example/foo
becomes/foo#<name1>
,/foo#<name2>
, ...operationId
(method name) is always unique, if not the method is renamedEndpoint.name
, method name is the default/fallbackO…