-
Notifications
You must be signed in to change notification settings - Fork 472
Allow creation of UriTemplates when pointing to controller methods. #169
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
Comments
It is possible. You should use For Example: @RequestMapping(method = RequestMethod.GET)
public HttpEntity<PagedResources<Resource<?>>> viewResources(Pageable pageable, PagedResourcesAssembler<?> assembler)
{
...
// query your repository
List<?> resources = ...
...
return new ResponseEntity<PagedResources<Resource<?>>>(assembler.toResource(new PageImpl<?>(
resources,
pageable,
resources.size())), HttpStatus.OK);
} ? is whatever resource class you are querying. The response should be like this:
|
The key of your example seems to be PagedResourcesAssembler, as it's the responsible for build the link. However, this process looks a bit cumbersome for me, and would be nice to have a simpler method, and generic enough to add it to any resource, not just lists. |
Link link = ControllerLinkBuilder.linkTo(methodOn(YourController.class).yourMethod(...).withRel("yourRel");
DummyInvocationUtils.LastInvocationAware invocations = (DummyInvocationUtils.LastInvocationAware) ControllerLinkBuilder.methodOn(YourController.class).yourMethod(...);
DummyInvocationUtils.MethodInvocation invocation = invocations.getLastInvocation();
Method method = invocation.getMethod();
MappingDiscoverer discoverer = new AnnotationMappingDiscoverer(RequestMapping.class); //taken from ControllerLinkBuilder
String mapping = discoverer.getMapping(YourController.class, method);
UriTemplate uriTemplate = new UriTemplate(mapping);
List<TemplateVariable> variables = link.getVariables();
//the templated link
Link templatedLink = new Link(uriTemplate.with(new TemplateVariables(variables)), link.getRel()); |
A possible workaround in getByXXX scenarios is a class-level RequestMapping such as
Now, to point to getEventById with a templated URL you can say somewhere else:
resulting in a templated link like |
I have a similar issue, but a little tricky. My PublicBlogRestController has a method to get blog comment by ID:
I want my PublicBlogResource will have a templated link to its comment, like "/public/blogs/blog123/comments/{commentId}". Maybe UriTemplate class can partially expand the template with path parameter values, like setPathParameter(String, Object), so I can create link like this:
Does it make sense? Or any other options? |
I wonder if you guys have had any thoughts on this, a related problem also appears on this StackOverflow question. The solution of Chris DaMour kind of works, but only for non-required request-params. Digging into the code I didn't find an obvious solution, I think there are two underlying problems:
I found out that when using The workarounds are compilated and insufficient though, so it would be really nice to have a proper and easy way to generate templated links - they're so common in HAL, that it's painful to have to create them with hacks. In terms of signature maybe extra methods on the
It could then build the link using the variables set on the |
The HAL implementation in this project is really useless without a good support for templated urls. So, I really hope this could be prioritised. All other HAL implementations for Java has its own problems that prevents me from using it. HALBuilder for instance doesn't respect Jackson annotations in beans added to it. |
@lazee +1 My resource assembler classes are full of hack to work around this issue. Hope @olivergierke can fix it ASAP :) |
+1 |
👍 |
AffordanceBuilder from the feature/affordances branch, or from spring-hateoas-ext (maven released) allows to define templated URIs by passing null for variables that should be templated. Otherwise it aims to be a drop-in replacement for ControllerLinkBuilder. See also https://github.com/dschulten/hydra-java#affordancebuilder-for-rich-hyperlinks-from-v-0-2-0 We are working to get AffordanceBuilder into spring-hateoas, feedback appreciated. |
I'm also running up against this problem. I would normally use spring data rest, but in this particular case, I'm working on a project with a backend for which there is no suitable spring-data-xxx (jpa, elasticsearch, mongodb, etc) flavor. My solution was to just use hateoas directly and expose things similar to how you would expect from spring data rest -- but without a means of creating templated urls, its really difficult. Would really like to see this feature. |
+1 |
4 similar comments
+1 |
+1 |
+1 |
+1 |
I had this problem in the project that I'm currently working and I developed a framework to create links and templates from controller calls. It also allows the use of spel expressions to control link rendering. In the next major version it will be possible to generate links and templates using only annotations. The repository is https://github.com/osvaldopina/linkbuilder. Any feedback will be appreciated. |
+1 |
2 similar comments
+1 |
+1 |
Just a quick heads up for you guys, we're going to have this fixed in a larger effort that will bring in an advanced accordances model built by @dschulten. |
+1 |
2 similar comments
+1 |
+1 |
…ller methods. If not all parameters are handed to a fake controller method invocation, the resulting link is now becoming a URI template. That means there are some tiny changes to the general behavior: 1. Missing required parts (like a path segment) are not rejected immediately but only if the resulting link is expanded itself. 2. Missing request parameters now appear in the resulting link, either in mandatory form (e.g. ?foo={foo}) or optionally (e.g. /{?foo}). To resolve these, the Link has to be expanded in turn.
That should be in place now. |
@olivergierke I'm seeing templates generated in this format: |
That depends on whether the parameter is required (former format) or optional (latter format). Mixing the two, works, too, but if you see the former format, I am pretty sure, your |
Thanks for the quick response! Yes, that was exactly it. On a related note, what should I see when |
Would be nice to have an easy way of return URL templates directly. For instance, suppose we have a method like
I can reference an specific invocation with linkTo(methodOn(Controller.class).list("foo", 1, 20) but I think there is no easy way to reference a generic call without specifing the method parameters. Invoking with null results in a exception.
I would like to get something like
Is that possible?
Regards
The text was updated successfully, but these errors were encountered: