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.
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.
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/.
@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.