-
-
Notifications
You must be signed in to change notification settings - Fork 7.2k
[kotlin-spring][server] Feat: Allow implementation of arbitrary interface in DTOs (similar to x-implements from java-spring) #21950
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[kotlin-spring][server] Feat: Allow implementation of arbitrary interface in DTOs (similar to x-implements from java-spring) #21950
Conversation
){{/discriminator}}{{! no newline | ||
}}{{#parent}} : {{{.}}}{{! no newline |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This misuse of comments to prevent line break might be controversial. However it seemed to improve the readability as otherwise the line would be very very long. But I can do one-liner if it is preferred to this.
x-kotlin-implements: [ 'com.some.package.Named' ] | ||
x-kotlin-implements-fields: [ name ] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is the way the vendor extension is used - define the interface and then specify the actual fields that should have the override
keyword prepended.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
thanks for adding a test spec (used in java unit tests)
can we also include a samples generated from this spec by adding a yaml config file under ./bin/config and add the new folder to the github workflow (.github/workflows/samples-kotlin-client.yaml) to ensure the output compiles without issues?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool. I am on it. That definitely makes sense and I was wondering how the ability to compile is checked.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, I hope I did it correctly. It was definitely worthwhile as I uncovered a mistake in one of my template changes. I added the generated files (and manually added the interfaces the models must implement) and added the output folder to the samples-kotlin-client.yaml. Hope that is all that is needed for now - I guess the pipelines should now automatically pick it up for compilation?
* Values: {{#allowableValues}}{{#enumVars}}{{&name}}{{^-last}},{{/-last}}{{/enumVars}}{{/allowableValues}} | ||
*/ | ||
enum class {{classname}}(@get:JsonValue val value: {{dataType}}) { | ||
enum class {{classname}}(@get:JsonValue val value: {{dataType}}) {{#vendorExtensions.x-kotlin-implements}}{{#-first}}: {{{.}}}{{/-first}}{{^-first}}, {{{.}}}{{/-first}}{{/vendorExtensions.x-kotlin-implements}}{ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think implementing the interface on enum is a bit useless as the only thing one can implement on generated enum is an interface with some default methods? Or correct me if I am wrong.
I did it here mostly to achieve parity with java x-implements
.
@get:Pattern(regexp="^[a-zA-Z0-9]+[a-zA-Z0-9\\.\\-_]*[a-zA-Z0-9]+$") | ||
@get:JsonProperty("name") val name: kotlin.String? = null | ||
) : Serializable{ | ||
) : Serializable { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just formatting changes - there are lot of those.
Thanks for the PR but your commit (as shown in the Commits tab) is not linked to your Github account, which means this PR won't count as your contribution in https://github.com/OpenAPITools/openapi-generator/graphs/contributors. Let me know if you need help fixing it. |
List<String> implementedInterfacesClasses = (List<String>) m.getVendorExtensions().getOrDefault(VendorExtension.X_KOTLIN_IMPLEMENTS.getName(), List.of()); | ||
List<String> implementedInterfacesFields = implementedInterfacesClasses.isEmpty() | ||
? List.of() | ||
: (List<String>) m.getVendorExtensions().getOrDefault(VendorExtension.X_KOTLIN_IMPLEMENTS_FIELDS.getName(), List.of()); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Would it make sense to log some info
or warn
here if the x-kotlin-implements-field
is defined on the model without corresponding x-kotlin-implements
? To make it a bit more user-friendly?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sounds good to me. please add some log
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
added
f61c542
to
7198cdd
Compare
… extends interface.
…n-implements to improve usability
c7ba56c
to
3d78287
Compare
I added the warn logs as well as more complex case of the arbitrary interface being extended by a schema with discriminator - hence generated interface extending the custom interface. Is anything more needed? I also tried to fix the issue with the email in commits - hope I did it correctly. |
… Pet.Status in implementations. This is a separate bug - not caused by x-kotlin-implements
3da9b01
to
212d2cc
Compare
I removed the "status" enum from Pet definition as it fails to generate code that will compile. This is not caused by my changes - it is some already existing bug related to how inner enums are handled in inheritance. |
👌 agreed we can look into that later with a separate pr to fix it |
…face in DTOs (similar to x-implements from java-spring) (OpenAPITools#21950) * add basic implementation and tests * improve test a bit * modify kotlin-spring.md * add x-kotlin-implements also to enum * update samples & properly define implemented vendor extension * use enum.getName() instead of hardcoded string as key in vendor extension map * fix docs * fix test openapi spec and test * add samples for x-kotlin-implements * add samples for x-kotlin-implements to proper output folder * fix * revert unwanted changes * move to correct place * fix mustache template * add to samples-kotlin-server.yaml * reuse 1 open api schema for everything. Add also case where interface extends interface. * add warn logs when x-kotlin-implements-fields is used without x-kotlin-implements to improve usability * remove unnecessary generated files * remove unnecessary generated files * remove "status" inner enum from Pet as it fails to properly import as Pet.Status in implementations. This is a separate bug - not caused by x-kotlin-implements
This PR adds support for two new vendor extensions named
x-kotlin-implements
andx-kotlin-implements-fields
.x-kotlin-implements
- a list of fully qualified interface(s) that should be implemented by a DTOx-kotlin-implements-fields
- a list of fields that are backed by the interface(s). This is necessary because unlike java, one has to add a keywordoverride
in front of the fields originating from the interfaces. The open api generator has no way of knowing which fields exist in the interfaces, so the fields names have to be provided via this vendor extension for the code to compile correctly. Ifx-kotlin-implements
is missing on the schema definition, this extension is ignored entirely.I implemented some basic tests - verified that my changes do not break the current way of handling inheritance and Serializable implementation. Also the java logic related to the implementation is in such a place that it should allow for a pretty easy implementation of the feature in the other kotlin code generators. I want to gather feedback whether this approach is acceptable. I decided against reusing
x-implements
as I can imagine the same swagger document being used in environments with mixed tech-stack, so I though that being able to implement different interfaces for java and kotlin might be useful. But I am ok with changing the extensions tox-implements
andx-implements-fields
if it increases the chance of having this merged into the codebase.I could not find an issue ticket for exactly this issue, so I went ahead and created the PR without linking anything. I hope it is ok.
PR checklist
Commit all changed files.
This is important, as CI jobs will verify all generator outputs of your HEAD commit as it would merge with master.
These must match the expectations made by your contribution.
You may regenerate an individual generator by passing the relevant config(s) as an argument to the script, for example
./bin/generate-samples.sh bin/configs/java*
.IMPORTANT: Do NOT purge/delete any folders/files (e.g. tests) when regenerating the samples as manually written tests may be removed.
master
(upcoming7.x.0
minor release - breaking changes with fallbacks),8.0.x
(breaking changes without fallbacks)"fixes #123"
present in the PR description)