spring-projects / spring-projects/spring-data-rest
Allow return of intermediate resources when traversing releations [DATAREST-412]
@odrotbohm is already working on this.
Since Dec 31, 2020.
- Dominant language
- Java
- Stars
- 958
- Forks
- 568
- PR merge metrics
- No merged PRs in 30d
Description
daniel carter opened DATAREST-412 and commented
This Issue relates to Traverson, which is part of spring-hateoas, as a client to spring-data-rest. Hateoas doesn't have JIRA project, so hopefully this is the correct place for tickets.
When using Traverson, i can only retrieve the resource at the end of the traversal. It is often useful to retrieve the intermediate objects.
For instance i have CREDENTIALS, which are linked to an IDENTITY, which has a (main) CONTACT which has some ROLEs.
For a credential, i want to retrieve the identity and its contacts roles.
This gives me the contact roles, but there is no way to get at the identity.
Traverson t = new Traverson(new URI("http://127.0.0.1:8090/"), MediaTypes.HAL_JSON);
t.setRestOperations(template);
Map<String, Object> params = new HashMap<>();
params.put("name", "V6UqkSG8");
params.put("type", "myType");
String contactUuid = t.follow("credentials", "search", "byNameAndType", "$_embedded.credentials[0]._links.identity.href", "mainContact", "roles")
.withTemplateParameters(params).<String> toObject(String.class);
I can retrieve both this way, but's it's ugly.
Traverson t = new Traverson(new URI("http://127.0.0.1:8090/"), MediaTypes.HAL_JSON);
t.setRestOperations(template);
Map<String, Object> params = new HashMap<>();
params.put("name", "V6UqkSG8");
params.put("type", "myType");
String identity = t.follow("credentials", "search", "byNameAndType", "$_embedded.credentials[0]._links.identity.href")
.withTemplateParameters(params).toObject(String.class);
LinkDiscoverer linkDiscoverer = new HalLinkDiscoverer();
Link contactLink = linkDiscoverer.findLinkWithRel("mainContact", identity);
t = new Traverson(new URI(contactLink.getHref()), MediaTypes.HAL_JSON);
t.setRestOperations(template);
String contactRoles = t.follow("roles").<String> toObject(String.class);
A few options
- Traverson could be stateful, retrieving an object and remembering it to allow a subsequent follow to resume from that resource
String identity = t.follow("credentials", "search", "byNameAndType", "$_embedded.credentials[0]._links.identity.href").toObject(String.class);
String contactRoles = t.follow("mainContact", "roles").toObject(String.class);
- Traverson could store everything for later retrieval
String contactRoles = t.follow("credentials", "search", "byNameAndType", "$_embedded.credentials[0]._links.identity.href", "mainContact", "roles").toObject(String.class);
String contact = t.retrieveFromTraverse("mainContact").toObject(String.class);
String identity = t.retreiveFromTraverse("$_embedded.credentials[0]._links.identity.href").toObject(String.class);
- Traverson could optionally return some sort of intermediate object to hold state
TraversonState identityTS = t.follow("credentials", "search", "byNameAndType", "$_embedded.credentials[0]._links.identity.href").toState();
String identity = identityTS.toObject(String.class);
String contactRoles = identityTS.follow("mainContact", "roles");
All much clearner looking than
String identity = t.follow("credentials", "search", "byNameAndType", "$_embedded.credentials[0]._links.identity.href")
.withTemplateParameters(params).toObject(String.class);
LinkDiscoverer linkDiscoverer = new HalLinkDiscoverer();
Link contactLink = linkDiscoverer.findLinkWithRel("mainContact", identity);
t = new Traverson(new URI(contactLink.getHref()), MediaTypes.HAL_JSON);
t.setRestOperations(template);
String contactRoles = t.follow("roles").<String> toObject(String.class);
PS. It would be nice if spring-data-rest would return a single object from a query method whoose signature returns a single entity to avoid all the "$_embedded.credentials[0]._links.identity.href" stuff.
Affects: 2.2.1 (Evans SR1)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.