spring-projects / spring-projects/spring-hateoas

Handling composite template variables in links and UriTemplate expansion

Open
#1,347 2 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
Java
Stars
1.1k
Forks
476
PR merge metrics
No merged PRs in 30d

Description

I'm having some issues with building a link to a method where I think the template variable should be a composite parameter (i.e. {paramName*}).

I have a controller with a "search-like" method, which can take arbitrary key=[value] parameters, with the declaration:

    @PostMapping("/{entityId}/populateFromSearch")
    @Transactional
    public ResponseEntity populateFromSearch(@PathVariable UUID entitytId, @RequestParam MultiValueMap<String, String> searchParameters)

I'm adding a link to this on my EntityModels, using the normal form: linkTo(methodOn(MyController.class).populateFromSearch(null, null).withRel("populateFromSearch")

This produces a URI template ending /populateFromSearch?searchParameters={searchParameters}. But this can't be expanded as a composite parameter by the UriTemplate class. Even if the parameterised part were correct ({searchParameters*}) the expansion leaves the original query parameter in place, i.e. ?searchParameters=&foo=qux&baz=buz.

My other approach is to manually set up the Link from a UriTemplate and manually add a TemplateVariable:

        resource.add(Link.of(
                UriTemplate.of(linkTo(DataBasketRepositoryExtension.class).slash(entityId).slash("populateFromSearch")
                                .toUriComponentsBuilder().build().toUriString(),
                        new TemplateVariables(TemplateVariable.compositeParameter("searchParameters"))),
                "populateFromSearch"
        ));

This produces a 'working' URI (ending with /inputSearch{*searchParameters}) but this brings me to the second issue: there's an incompatibility between TemplateVariable.compositeParameter("foo") and uriTemplate.expand.

The TemplateVariable is rendered {*paramName} (ref), while the expansion expects the composite marker to be at the end of the parameter (i.e. {paramName*} (ref).

This is a bit frustrating, but can be worked around using the manual link approach - I can just append the {searchParameters*} string manually when building the UriTemplate.

Contributor guide

No contributing guide indexed for this repository

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with TemplateVariable.java around compositeParameter and UriTemplate.java around the expansion logic referenced in the issue. Reproduce the link-generation and expansion examples for searchParameters, then inspect how composite query variables are rendered and parsed. Done means the two paths agree on composite-variable syntax and the resulting URI expands without retaining an incorrect placeholder.

Written by the indexing model from the issue text.

Assessment

Tech stack
java, spring
Domain
api
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
45/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.