When i generate code for Spring
from my swagger yaml , usually controller layer is generated using delegate
pattern , such that for a single model three files are generated . For example , if i defined a model named Person
in my swagger/open API yaml file , three files get generated as :
- PersonApi (interface that contains signatures of all person operations/methods)
- PersonApiDelegate ( interface that provides default implementation of all PersonApi methods . Meant to be overriden )
- PersonApiController (Which has a reference to PersonApiDelegate so that any implementation can override and provide custom implementation)
My question is for anyone who is familiar with building swagger/openapi generated code based apis that what is the significance of having such a pattern , instead of just exposing your service endpoints using a PersonController class , and not going through a PersonApi interface and then to a PersonApiDelegate and finally exposing the service through a PersonApiController ?
What is the valuable design extensibility we gain through this pattern ? I tried to find information from other resources on internet , but couldn't find a good answer in context of swagger first API development approach . Any insights on this will be really helpful .
First of all a clarification: as already mentioned in a comment, you are not forced to use the delegation. On the contrary, the default behavior of the Spring generator is to not use the delegation pattern, as you can easily check in the docs. In this case it will generate only the PersonApi interface and PersonApiController.
Coming to your question, why using delegation?
This allows you to write a class that implements PersonApiDelegate, that can be easily injected in the generated code, without any need to manually touch generated sources, and keeping the implementation safe from possible future changes in the code generation.
Let's think what could happen without delegation.
A naive approach would be to generate the sources and then write directly the implementation inside the generated PersonController. Of course the next time there is a need to run the generator, it would be a big mess. All the implementation would be lost...
A slightly better scenario, but not perfect, would be to write a class that extends PersonController. That would keep the implementation safe from being overwritten during generation, but would not protect it from future changes of the generation engine: as a bare minimum the implementation class would need to implement the PersonController constructor. Right now the constructor of a generated controller has the following signature PersonApiController(ObjectMapper objectMapper, HttpServletRequest request)
, but the developers of the generator may need to change it in the future. So the implementation would need to change too.
A third approach would be to forget completely about the generated PersonApiController, and just write a class that implements the PersonApi interface. That would be fine, but every time the code is generated you would need to delete the PersonApiController, otherwise Spring router will complain. Still manual work...
But with the delegation, the implementation code is completely safe. No need to manually delete stuff, no need to adapt in case of future changes. Also the class that implements PersonApiDelegate can be treated as an independent service, so you can inject / autowire into it whatever you need.