Skip to content
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

Inherit value for @RequestMapping if not overridden [SPR-11421] #16048

Closed
spring-projects-issues opened this issue Feb 12, 2014 · 3 comments
Closed
Assignees
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) status: declined A suggestion or change that we don't feel we should currently apply type: enhancement A general enhancement

Comments

@spring-projects-issues
Copy link
Collaborator

spring-projects-issues commented Feb 12, 2014

Christopher Smith opened SPR-11421 and commented

If a @RequestMapping path is defined on a superclass, the path is inherited by subclasses (e.g., the @RequestMappings on their methods are relative to the superclass's base path).

I'm using the Spring content negotiation feature to serve both HTML views and a JSON API from the same URLs, based on the client's Accept header. In order to overload the URL, I have to differentiate the implementation methods by having different produces attributes; I specify "application/json" in the @RequestMapping for the JSON subclass.

The value attribute on @RequestMapping is not required, but if a subclass is annotated, Spring overrides the path from the parent with an empty string and attaches the subclass's controllers to the root path.

In order to avoid having to duplicate @RequestMapping data on each class, I suggest changing the resolver to treat a missing value attribute in a @RequestMapping as if the annotation were not there, rather than implicitly treating it as an empty string. The behavior of a @RequestMapping on a subclass without a value attribute is not specified by the docs, so this wouldn't break the existing contract. In the alternative, I suggest making value a required attribute to eliminate this pitfall.


Affects: 4.0.1

Attachments:

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Feb 12, 2014

Rossen Stoyanchev commented

Please post example controller and method declarations to clear out any possible ambiguity around how exactly your request mappings are defined.

In general method-level annotations extend type-level annotations. We also look for annotations in the controller's hierarchy but we stop stop at the first annotation we find. We don't continue to search and then merge any additional annotations that may be on super types.

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Feb 12, 2014

Christopher Smith commented

This is the test sample I've been working with. The annotation on AbstractController specifies the prefix for the whole controller class, and it's correctly inherited by the HtmlController. The value has to be repeated on the JsonController, however, because it needs a produces attribute to distinguish it for the DispatcherServlet. Either the JsonController should be able to inherit "/timesten/*" if its mapping has no value, or the value attribute should be required.

The code as posted works (with a trivial Spring Boot launcher). Removing the mapping from JsonController results in a clash between the two controllers, and just having the produces attribute binds it to / instead of /timesten/.

@spring-projects-issues
Copy link
Collaborator Author

spring-projects-issues commented Feb 14, 2014

Rossen Stoyanchev commented

Okay, I see now. Thanks for the detail.

@RequestMapping annotations are supported on the type and method-level, where method-level annotations inherit or extend type-level metadata. For example type-level patterns are treated as a prefix, HTTP methods (also headers and params) are inherited, while consumes/produces conditions override type-level choices. This is a model that is manageable in terms of comprehension.

Having an additional dimension where both type and method-level annotations are merged with annotations on parent methods is IMO a significantly more complex model, one that can become very difficult to comprehend. The use case you have in mind is quite straight forward and makes sense. However, the general range of options it creates is not.

If you're concerned about duplicating metadata, you can create a constant for the AbstractController type-level mapping and re-use it in JsonController. It may make your case slightly more complex but that's a trade-off.

@spring-projects-issues spring-projects-issues added status: declined A suggestion or change that we don't feel we should currently apply type: enhancement A general enhancement in: web Issues in web modules (web, webmvc, webflux, websocket) labels Jan 11, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
in: web Issues in web modules (web, webmvc, webflux, websocket) status: declined A suggestion or change that we don't feel we should currently apply type: enhancement A general enhancement
Projects
None yet
Development

No branches or pull requests

2 participants