I developed a framework for rendering links in spring hateoas and supports annotated parameters ( @PathVariable and @RequestParam ) and arbitrary parameter types.
To execute these arbitrary types, you need to create a spring bean that implements the com.github.osvaldopina.linkbuilder.argumentresolver.ArgumentResolver interface.
The interface has 3 methods:
public boolean resolveFor(MethodParameter methodParameter)
Used to determine if ArgumentResolver can be used to work with methodParameter . For instance:
public boolean resolveFor(MethodParameter methodParameter) { return UserDefinedType.class.isAssignableFrom(methodParameter.getParameterType()); }
Specifies that this ArgumentResover will be used for UserDefinedType .
public void augmentTemplate(UriTemplateAugmenter uriTemplateAugmenter, MethodParameter methodParameter)
Used to include in the uriTemplate associated with the method the corresponding parts of the template. For instance:
@Override public void augmentTemplate(UriTemplateAugmenter uriTemplateAugmenter, MethodParameter methodParameter) { uriTemplateAugmenter.addToQuery("value1"); uriTemplateAugmenter.addToQuery("value2"); }
Adds 2 query patterns (value1 and value2) to the uri pattern.
public void setTemplateVariables(UriTemplate template, MethodParameter methodParameter, Object parameter, List<String> templatedParamNames)
Sets the values ββfor template variables in the template. For instance:
@Override public void setTemplateVariables(UriTemplate template, MethodParameter methodParameter, Object parameter, List<String> templatedParamNames) { if (parameter != null && ((UserDefinedType) parameter).getValue1() != null) { template.set("value1", ((UserDefinedType) parameter).getValue1()); } else { template.set("value1", "null-value"); } if (parameter != null && ((UserDefinedType) parameter).getValue2() != null) { template.set("value2", ((UserDefinedType) parameter).getValue2()); } else { template.set("value2", "null-value"); } }
receives an instance of UserDefinedType and uses it to set the template variables value1 and value2 defined in the augmentTemplate method.
A ArgumentResolver full example:
@Component public class UserDefinedTypeArgumentResolver implements ArgumentResolver { @Override public boolean resolveFor(MethodParameter methodParameter) { return UserDefinedType.class.isAssignableFrom(methodParameter.getParameterType()); } @Override public void augmentTemplate(UriTemplateAugmenter uriTemplateAugmenter, MethodParameter methodParameter) { uriTemplateAugmenter.addToQuery("value1"); uriTemplateAugmenter.addToQuery("value2"); } @Override public void setTemplateVariables(UriTemplate template, MethodParameter methodParameter, Object parameter, List<String> templatedParamNames) { if (parameter != null && ((UserDefinedType) parameter).getValue1() != null) { template.set("value1", ((UserDefinedType) parameter).getValue1()); } else { template.set("value1", "null-value"); } if (parameter != null && ((UserDefinedType) parameter).getValue2() != null) { template.set("value2", ((UserDefinedType) parameter).getValue2()); } else { template.set("value2", "null-value"); } } }
and for the following link builder:
linksBuilder.link() .withRel("user-type") .fromControllerCall(RootRestController.class) .queryParameterForUserDefinedType(new UserDefinedType("v1", "v2"));
the following method:
@RequestMapping("/user-defined-type") @EnableSelfFromCurrentCall public void queryParameterForUserDefinedType(UserDefinedType userDefinedType) { }
will create the following link:
{ ... "_links": { "user-type": { "href": "http://localhost:8080/user-defined-type?value1=v1&value2=v2" } ... }
}