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
Ability to provide an external base path for controllers [SPR-16336] #20883
Comments
Rossen Stoyanchev commented Indeed this issue has been raised in several tickets.
Aside from the ability to assign a common prefix, a second common thread is the ability to choose what prefix to apply to which controllers. |
Caleb Cushing commented a comment I want to make in regards to a package-info, or abstract base class, although I don't hate either idea, and I think they're good ideas, I think they don't work well in a post Jigsaw world for what I want. Reason being is is that jigsaw exports packages in a globally unique way, and abstract base class means a dependency. In a post jigsaw world it would be ideal to allow remapping when composing jigsaw modules so that the module can be reused (perhaps even ideally within the same application, e.g. remapping the same thing many times) thought, pseudocode, nothing is saying this is the right design for the problem, just that it could show something powerful
resulting in
update, immediately thought better of wanting templates in this, that sounds like a major pain if writing generic controllers if class provided is an annotation, apply to all controllers annotated as such. |
Rossen Stoyanchev commented My current plan to experiment with:
In other words a simple mechanism to enrich request mappings with a prefix, as part of the normal process of registration. Note that anything that builds links to controllers (MvcUriComponentsBuilder, or the ControllerLinkBuilder from Spring HATEOAS) will need to be enhanced in order to be aware of those prefixes. Spring Boot Actuator, which shows request mappings, will probably be okay, since it gets those through I think Spring Security should be okay as far as I can think. /cc Rob Winch Oliver Drotbohm, Greg Turnquist, any thoughts from a Spring Data REST perspective, whether this is helpful and/or require changes? |
Andy Wilkinson commented Thanks for considering the possible effects on Boot, Rossen. Actuator doesn't just use
|
Rossen Stoyanchev commented Thanks Andy, I think for now this will apply to annotated controllers only. |
Rossen Stoyanchev commented Support for path prefixes is now available in master. It's configurable directly on Caleb Cushing, and everyone else, if you have a chance please take a look to see if this meets your needs. |
Stanislav Bytsko commented Given: configurer.addPathPrefix("/api", HandlerTypePredicate.forAnnotation(Controller.class));
@Controller
public abstract class JsonErrorController implements ErrorController {
@Override
public String getErrorPath() {
return "/error";
}
@RequestMapping("/error")
public ResponseEntity<JsonApiErrors> error(HttpServletResponse response) {
... custom error
}
} I don't see how not, but it would be nice to exclude this behaviour somehow, so that error will be forwarded correctly |
Rossen Stoyanchev commented First off, thanks for taking a look. The So yes if you target
|
Caleb Cushing commented looking at the sample here, and through the code a little bit. HandlerTypePredicate.forPackage("com.xenoterracide").and(HandlerTypePredicate.ForAnnotation(Controller.class) such that it requires the union of both and not just one or the other? also what is the behavior if you add, multiple paths, especially if they overlapp (RestController, isa Controller), what happens if I swap the order when adding? "/ui/", HandlerTypePredicate.forAnnotation(Controller.class)
"/api/", HandlerTypePredicate.forAnntoation(RestController.class)
and lastly will I be able to do this @Controller
@RequestMapping("")
MyClass {...}
"/api/user", HandlerTypePredicate.forClass(MyClass.class)
"/api/other", HandlerTypePredicate.forClass(MyClass.class) such that I can use the same controller twice, at different endpoints. I will take a closer look this weekend. |
Rossen Stoyanchev commented Yes I should change the config to accept For the order, the first matching prefix-predicate pair wins. This is mentioned this in the Javadoc. As for registering the same controller twice, the answer is no. This does not declare or controller what controller instances are registerred, rather it intercepts mappings as they are being registered, and tries to match based on controller type + enrich the mapping patterns. There would have to be two public class HandlerBeanPredicate implements BiPredicate<String, Class<?>> {
// ...
} Do you have use case like that or just checking? |
Caleb Cushing commented
I do actually, and it's probably not all that different from spring data rests's general use case, at some point you can write controller code so generic, that it would work if attached in multiple places. In this case I believe you would have to look at the Generics of the class though... or maybe some other parameter... like a class passed to a constructor... thinking outloud. For example, I'm currently needing to write endpoint code for JSON Schema v4, so that I have endpoints that conform to SDR, but use non-persistable DTOs. The only difference between the controller code in this case would be the DTO class. everything else about this would just be reflective, and accessed at different endpoints. |
Rossen Stoyanchev commented I switched to using |
Caleb Cushing commented
also yeah, in the 2nd comment of the thread I added this
though thinking about it, this should work as is right? same controller just different endpoint... .... though considering the ... if you'd like I can try to come up with a useful use case for an |
Rossen Stoyanchev commented We iterate over bean names so no access to instances, which may not have been created. Looking at the code, bean names are also currently not available in the method that extracts information from
|
Caleb Cushing commented
yes, which means I could also just add a different
I didn't find any mention in the reference docs, most of the googles are using xml config and the javadoc is kind of vague as to how to use it. I'm not opposed to relying on |
Rossen Stoyanchev commented Good idea. I'll add some around here. |
Rossen Stoyanchev commented Done. While the snapshot is building, you can see the documentation source. |
Caleb Cushing commented I think I can be happy with that. I did make 2 comments on your source diff, I think you may have typoed/copy pasta-ed the class name instead of the arg name. But that's a minor fix. |
Caleb Cushing commented btw, thanks for all the hard work, and acceptance of feedback, this looks awesome! I need to give it a go soon. |
Rossen Stoyanchev commented I've updated |
Caleb Cushing opened SPR-16336 and commented
I'm certain wrote, or commented on a similar bug that I currently can't find. I'd like the ability to do this with classes annotated with
@Controller
, and perhaps separately for@RestController
.in this way one could write a generic controller with a known subpath, such as /register, but then attach it in the final application as, in my case, /v0/public/register. Suggestions for more flexibility might be a way to setBasePath, explicitly based on annotation.
so you could write
config.setBasePath( PublicController.class, "/v0/public" )
where@PublicController
is an extension of@Controller
, or maybe it'd just be a good idea to allow it for the specific class insteadone of the reasons I have this problem is I'm modularizing all of my components, but now I have to ensure that these paths are configured properly for hateoas before writing a controller, because the controllers path is static, thus changes to hateoas roots for links have to be made before the controller for tests. If I could change the base path of the controller later then I could bundle the controllers under a configuration, and they'd be more reusable modules between apps, and completely configurable.
Affects: 5.0.2
Issue Links:
@RequestMapping
("supersedes")@RequestMapping
at package level ("supersedes")Referenced from: commits 58cce61, 928b780, 86c8615, d196cdc, 19dc981, 31159a8, e6fef95
2 votes, 7 watchers
The text was updated successfully, but these errors were encountered: