-
Notifications
You must be signed in to change notification settings - Fork 38.3k
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
Enable REST controller method parameter annotations on an interface [SPR-11055] #15682
Comments
George Georgovassilis commented There is an implementation here: https://github.com/ggeorgovassilis/spring-rest-invoker |
George Georgovassilis commented Upon re-reading the ticket's description, the submitter asks for a common interface that would work both for controllers that expose REST APIs and clients that consume them. The implementation above generally requires interfaces that might not make sense when implemented by a controller. |
Rossen Stoyanchev commented Controller annotations can be inherited from a base class or interface. Method parameter annotations however cannot be. They must be directly on the controller method in all cases. This ticket is a request to change that. Indeed your proposal has similar purpose but does not depend on this ticket since in your case the interfaces are only used for generating a client proxy. That said once the ability to create a client proxy from an interface with the same annotations is available, it becomes a natural question: should it be possible for a controller and a client proxy to share an interface? |
George Georgovassilis commented In that case I'd like to decouple my implementation from the concrete decision whether a single or multiple interfaces are to be used. New ticket #16747. |
Matt Benson commented This issue also applies to parent classes. |
Matt Benson commented PR submitted: #976 |
Rossen Stoyanchev commented Wow this is a very extensive effort and a perfect example of the sort of thing that you could discuss (beforehand) on our contributor's mailing list. Style and programming model issues aside, there is a whole separate discussion if we should even re-use the same annotations for client-proxy generation or create more dedicated annotations for the purpose (see #16827). Alternatively with what we have today wouldn't it be easy to generate interfaces on the fly from a controller's methods and annotations? That way method parameter annotations can remain close to the class as promoted by the programming model today. |
Matt Benson commented TBH I decided to take my chances rather than subject my inbox to the burden of another mailing list. With regard to client proxies, spring-cloud is already doing this with their support for Netflix Feign, and until recently their documentation (at least somewhat erroneously) reported that it was possible to use a Spring-annotated REST interface for client and server alike. The non-inherited nature of parameter annotations is in fact the missing ingredient here. If people are going to use interfaces for client proxies, I can't see how forcing them to define their REST API in multiple places does anything other than expose them to the risk that these definitions will fall out of sync. My interpretation of "on the fly" is "at runtime." I don't see how that helps clients who want to consume the hypothetical generated interface. Certainly it would be possible to generate such an interface, but it seems like this would be more a tooling step or, at best, an annotation processor, and getting these generated types into a consumable client artifact would be quite a build-system-dependent task. It is not at all clear to me that this solution would be better than a basic, Java-based one. |
Matt Benson commented With the recent closure of the development forum, do any other Spring developers have any thoughts on the proposed fix? |
Rossen Stoyanchev commented If we did implement this feature to allow method parameter annotations on supertypes it would most likely be exposed through From a Spring MVC perspective I think basic support for the Spring Cloud with Netflix Feign use case (i.e. allow the same interface to be used on client and server side)is fine as a use case but allowing a method parameter to be anywhere is another matter. It means for a controller method with several arguments the annotations for each argument could literally be in a different superclass. I'm not sure it should be so wide open. Some meaningful constraints focusing on the target use cases we want to support should perferably be in order. |
Alexandre Navarro commented +1 |
Elias O commented One more use case for method param annotation inheritance: |
Yura Nosenko commented
|
Yura Nosenko commented When it comes to validation, there is a workaround - |
Rossen Stoyanchev commented Do you mean that Swagger can't generate a class for a server stub, and same for RAML? |
Elias O commented Rossen Stoyanchev that mean that if you use Swagger codegen, you can choose an "API [interfaces] only" option that generates API interfaces like this: public interface Resource {
@RequestMapping
void do(@RequestParam String name, @RequestBody DTO value);
} so that you may expect your controller to look like this: @RestController
public class ResourceImpl implements Resource {
void do(String name, DTO value) {
// do stuff
}
} ResourceImpl#do will inherit The only way to make it work is to duplicate arg annotations: @RestController
public class ResourceFixedImpl implements Resource {
void do(@RequestParam String name, @RequestBody DTO value) {
// do stuff
}
} In real cases, such interfaces can have tons of annotations (moreover, arg annotations tend to become very long) and it makes sense to leave them aside from the implementation. To overcome this bug, currently swagger can generate api + implementation (with annotated params) + delegation interface, so that users can implement a delegation interface only. |
Alexandre Navarro commented Hi, I will explain our use case why we want to implement In my firm, we have developped java microservice (around 20) with spring, spring-boot and spring-cloud with So this is the reason why I really want to have this feature. I understand you have to set some rules if for instance some annotations in the implementation are different in the interface (potentially they can be contradictory). In my point of view, you should take first the annotations of the interface and potentially add / override it if the implementation add / override some annotations. It can be useful because
This is just my point of view on the rule to adopt between interfact / implemenation annotations, maybe you have some other arguments to decide apply different rules between annotations declared in Thanks in advance to implement this feature, it will be really really useful.
|
Damian Sima commented Hi guys, can we have an update from the eng team about this? I mean the issue was open un 2013 and it is still active but unresolved, are we gonna have a feature for this? Cheers! |
Andrey Gliznetsov commented I'd like to add that some annotations actually work on interface, f.e. |
Juergen Hoeller commented I'm happy to report that this is finally resolved in master now, in time for the 5.1 RC1 release! Feel free to give it an early try against the upcoming |
George Georgovassilis commented Thank you Juergen Hoeller |
Damian Sima commented you rock Juergen Hoeller |
@jhoeller hi,how can I achieve the same effect in spring5.0.x? |
When forming links, look at a controller class's interface definitions for possible Spring Web annotations. Related issues: spring-projects/spring-framework#15682
When forming links, look at a controller class's interface definitions for possible Spring Web annotations. Related issues: spring-projects/spring-framework#15682
When forming links, look at a controller class's interface definitions for possible Spring Web annotations. Related issues: spring-projects/spring-framework#15682
When forming links, look at a controller class's interface definitions for possible Spring Web annotations. Related issues: spring-projects/spring-framework#15682
When forming links, look at a controller class's interface definitions for possible Spring Web annotations. Related issues: spring-projects/spring-framework#15682 Original pull request: #1194.
When forming links, look at a controller class's interface definitions for possible Spring Web annotations. Related issues: spring-projects/spring-framework#15682 Original pull request: #1194.
Paweł Mendelski opened SPR-11055 and commented
Please, enable inheritance of controller related annotations from implemented interfaces.
I would like to share rest service interface between client and server. This way I could provide a really convenient mechanism - client-proxy, like the one RestEasy provides.
Shared interface:
Server implementation:
Client code:
At the moment I cannot write
SpringMvcProxyFactory
because parameter annotations from interfaceRandomDataController
are not inherited byRandomDataControllerImpl
.Affects: 4.3.3
Issue Links:
@RequestBody
annotation in interface is ignored ("is duplicated by")@Path
) annotated with@RequestMapping
are not supported when you create a@RestController
via an Interface ("is duplicated by")@RequestMapping
annotations as an interface for HTTP clients ("is duplicated by")@RequestBody
,@PathVariable
...) to be defined on interfaces or parent classes ("is duplicated by")@PathVariable
on interface method ("is duplicated by")@RequestMapping
) in super class@DateTimeFormat
annotations are necessary both on field and constructor parameter in the immutable form classReferenced from: commits 790d515, 1f5d0fa
30 votes, 37 watchers
The text was updated successfully, but these errors were encountered: