One thing I do not understand when using ControllerLinkBuilder with methodOn feature is what are you suppose to do when your Controller has method signature like so:
public HttpEntity<ResourceSupport> update(@PathVariable(USER_ID) Long userId, @Valid @RequestBody UserUpdateRequest userUpdateRequest, BindingResult bindingResult)
So whenever I wish to use methodOn, how am I to fill the blanks like UserUpdateRequest argument and BindingResult (I use binding result to handle bad request exceptions with @ControllerAdvice and JSR 303 to make output messages human readable).
When I wish use out of the box spring HATEOAS ControllerLinkBuilder for more ease with methodOn I end up writing something like this (mind me I do not know if this will not backfire but the code does not look comforting):
resource.add(linkTo(methodOn(UserController.class).update(userId, null, null)).withSelfRel());
Ofcourse I can omit the methodOn part and just use linkTo which would then require me to play around building the path.
Is it appropriate to just pass on null refs ? Plus how is it convenient using methodOn as if you decide to remove say: BindingResult or add something like HttpServletRequest to the controller method signature so that spring could pass me more info about request if I wanted to log an IP address for some security reason. This would require me to go and change the link construction part using methodOn.
Another question that is bit boggling me is say I pass a legitimate ref to methodOn like userUpdateRequest filled with data - does that data suppose to go anywhere with the generated link ? I've seen some Hypermedia that include along with rel and href a body of what you pass - is that possible with Spring HATEOAS and is it a good practice to create links with ready to post/put payloads in them ?
But getting back to ControllerLinkBuilder using only linkTo method building links with .slash("...") - is it potentially less maintenance costly ?
In day to day practice what would you recommend and what do you think about link construction ? Maybe someone could provide professional tips/advices.
Thank You,
Spring HATEOAS provides some APIs to ease creating REST representations that follow the HATEOAS principle when working with Spring and especially Spring MVC. The core problem it tries to address is link creation and representation assembly.
Enhancing the resource to return HATEOAS response EntityModel is a simple class wrapping a domain object and allows adding links to it.
If a parameter is not needed to build the path you can safely pass null
to methodOn
. You can pass "real" data as only the data needed to build the path is actually used.
methodOn
is a double-edged sword. On the one hand it spares you from constructing links manually. So there won't be mistakes and if you change a path all links would still be correct. On the other hand you will almost certainly never change a path, but as you noted, you may change a method's signature. In that case you are forced to update the link building code too, because it won't compile otherwise. You cant't forget the update, so that's a good thing. Yet consider the following change:
update(@ModelAttribute Integer otherId,
@PathVariable(USER_ID) Long userId,
@Valid @RequestBody UserUpdateRequest)
methodOn(UserController.class).update(userId, null, null)
would still be semantically correct, so you don't get a compile error. Building the link will fail though.
IMHO the best way is to rely on automated link construction as much as possible like it's done by Spring Data REST. Your API should be simple and consistent enough to extract at least most of the link-creating code. The link would then be build using slash()
, not methodOn
.
As for including a body: The default format of Spring HATEOAS is HAL. It uses an _embedded
property to expose such data.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With