-
Notifications
You must be signed in to change notification settings - Fork 473
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
Sample for embedding HAL Resources of different types with root resource #270
Comments
+1 |
3 similar comments
+1 |
+1 |
+1 |
+1 here, too. Here's an example of one such Google result: http://stackoverflow.com/questions/25858698/spring-hateoas-embedded-resource-support |
In my mind, there are Entities, Resources and Resource Representations. An example can be Entities are Person & Address. A Resource can be PersonDetail, which is collection of Person and Address. A PersonDetail can be linked to Orders Resource via "allPastOrders". So, when, we want to represent PersonDetail Resource, i may for optimization reason, want to embed Orders Resource. There is already an API to link Resource. That allows us to design relationship between Resources. In order to avoid this long chain of things, perhaps having Resource Representation Annotations, that can be placed on a Resource, would help to determine whether to embed Resources or not?? |
+1 |
2 similar comments
+1 |
+1 |
+1. This issue and #169 are my pain using Spring HATEOAS with HAL. |
+1 |
Ultimately this feature is not supported with Spring HATEOAS. Embedding non collection resources must be done manually if you want to support the entire hal spec. Currently our team has decided to consider this a HAL light and we do not embed non list resources. Ultimately this issue should turn into a feature request. Thoughts? May want to create a new issue requesting support. |
I'd be interested in seeing a feature similar to what @anywhereinfo describes above.
I'm currently using spring-data-rest, and there seems to be no easy way to specify if a child resource should appear in the _embedded object. |
I might be missing something but this works out of the box: // Infrastructure setup, only needed for test case
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new Jackson2HalModule());
mapper.enable(SerializationFeature.INDENT_OUTPUT);
mapper.setHandlerInstantiator(new HalHandlerInstantiator(new EvoInflectorRelProvider(), null, null));
Resources<Object> resources = new Resources<>(Arrays.asList(new Animal("Dog"), new Person("Dave", "Matthews")));
System.out.println(mapper.writeValueAsString(resources)); Yields: {
"_embedded" : {
"persons" : [ {
"firstname" : "Dave",
"lastname" : "Matthews"
} ],
"animals" : [ {
"kind" : "Dog"
} ]
}
} Would anyone of you mind adding a sample of what you're expecting? It feels weird that so many people +1 this, when there isn't even an example of what's expected and I suspect a lot of the +1s here expecting something different than the original poster. |
I was thinking more along the lines of @anywhereinfo's second comment about an annotation to define which Resources to embed. This probably was not the right issue to +1, but It seemed closest to what I was looking to do. I haven't had any issues embedding a single object in the _embedded tag. |
Looking to embed a resource when implementing Examples: public class HypermediaModel implements ResourceSupport{
private String value;
@Embedded
private HypermediaSubModel subModel;
} Then serialized should yield:
A similar function on Resource class would be use-full if not implementing ResourceSupport. Resource<HypermediaModel> hypermediaResourceModel = new Resource(hypermediaModel, links); This would yield similar results. Maybe useful: hypermediaResourceModel.embed(...); Let me know if I'm off base on this request. |
You can embed more than just collections in HAL. How do you embed a single object? Ultimately our team decided to only place collections in embedded and provide links to associated resources. If we need to provide aggregate data we do it directly on the json object and not in embedded. Ultimately this is not proper to HAL spec and not supported by Spring HATEOAS from what I understand . |
+1 definitely need this, or at least a workable way to get around it for accepting resources with arbitrary |
Hi! We have an issue and I think it's related for this problem, but the difference is that we want do deserialize embedded resource with different type. There is an example how we build embedded resources with different type: And this is our question: |
@olivergierke
Assume the main JSON object is generated from
Untill now all is possible with spring-hateoas exept an array of object instead of a single object.
and now we want to embedd both the author and the illustrator. Both of them are of
Why? Because the relation name in the _embedded map is based on the type of the resource. The idea of In most cases resource embedding is the next step to resource linking (http://tools.ietf.org/html/draft-kelly-json-hal-07#section-8.3). If you think that a linked resource is follow in most use cases, you consider embedding it because of performance. Resource embedding should be similar to linking i.e. if you have I suggest to change 'Sample' into 'Support' in this issue title. |
Embedding a single object is part of the HAL spec draft Section 4.1.2 |
Any updates on this topic? Sideloading related data is quite important for many use cases. |
You've provided a very good example from the HAL spec. Embedding values for performance reasons makes sense and is clearly marked in the spec itself.
I think this providers a good test case to work against. |
I was expecting to find a miraculous |
? |
Any progress with this issue? Not being able to add single elements to class MyObject {
@JsonUnwrapped
private final Resources<EmbeddedWrapper> embeddeds;
MyObject(EmbeddableClass embeddable) {
embeddeds = new Resources<>(Arrays.asList(
new EmbeddedWrappers(false).wrap(embeddable)));
}
} |
I drafted a branch to poke at this issue and am working through various issues to not break everything else. |
The HAL spec shows an example of a single resource, embedded at the top level. Spring HATEOAS, up until this point, has only supports embedded for the purposes of collections.
Congratulations to this issue reaching its 3rd birthday 🎂. |
jkubrynski thinks the same as me! :) To make this work it would be ideal to have a class, that extends |
Is there a way we can deserialize responses from the spring.data.rest @RestResource annotated repository? In a much simpler way & not through hacking, unlike what I see on Stackoverflow. |
Given that I knew which properties I wanted to have embedded directly, the simplest way for me to just include one json-public method to my entity/ies with those embedded members: class WhateverParentEntity {
private List<ChildEntityType> whatEverChildEntities;
...
@JsonUnwrapped
private final Resources<EmbeddedWrapper> getEmbeddeds() {
List<EmbeddedWrapper> embedded = new ArrayList<>();
embedded.add(new EmbeddedWrappers(false).wrap(whatEverChildEntities));
return new Resources<>(embedded);
} |
Sorry I missed it, little one! Happy 4th birthday! 🎂 |
Using @GetMapping("/author/{id}")
CollectionModel<?> authorDetails(@PathVariable int id) {
EmbeddedWrappers wrappers = new EmbeddedWrappers(false);
List<Object> items = new ArrayList<>();
EntityModel<Author> authorModel = new EntityModel<>( //
new Author("Alan Watters", "January 6, 1915", "November 16, 1973"), //
new Link("/people/alan-watts"));
items.add(wrappers.wrap(authorModel, LinkRelation.of("author")));
EntityModel<Author> illustratorModel = new EntityModel<>( //
new Author("John Smith", null, null), //
new Link("/people/john-smith"));
items.add(wrappers.wrap(illustratorModel, LinkRelation.of("illustrator")));
CollectionModel<?> collectionModel = new CollectionModel<>(items);
collectionModel.add(new Link("/books/the-way-of-zen"));
collectionModel.add(new Link("/people/alan-watts", LinkRelation.of("author")));
collectionModel.add(new Link("/people/john-smith", LinkRelation.of("illustrator")));
return collectionModel;
} It generates this: {
"_embedded" : {
"author" : {
"name" : "Alan Watters",
"born" : "January 6, 1915",
"died" : "November 16, 1973",
"_links" : {
"self" : {
"href" : "/people/alan-watts"
}
}
},
"illustrator" : {
"name" : "John Smith",
"_links" : {
"self" : {
"href" : "/people/john-smith"
}
}
}
},
"_links" : {
"self" : {
"href" : "/books/the-way-of-zen"
},
"author" : {
"href" : "/people/alan-watts"
},
"illustrator" : {
"href" : "/people/john-smith"
}
}
} Perhaps you're thinking that returning a |
I'm working on a fluent API that builds the same thing. What do you think? @GetMapping("/author/{id}")
RepresentationModel<?> authorDetails(@PathVariable int id) {
return ModelBuilder //
.embed(LinkRelation.of("author")) //
.entity(new Author("Alan Watts", "January 6, 1915", "November 16, 1973")) //
.link(new Link("/people/alan-watts")) //
.embed(LinkRelation.of("illustrator")) //
.entity(new Author("John Smith", null, null)) //
.link(new Link("/people/john-smith")) //
.rootLink(new Link("/books/the-way-of-zen")) //
.rootLink(new Link("/people/alan-watts", LinkRelation.of("author"))) //
.rootLink(new Link("/people/john-smith", LinkRelation.of("illustrator"))) //
.build();
} |
@gregturn if I remember correctly, |
If you look at the first HAL document shown on the spec you’ll find links on multiple levels. |
@gregturn ok, good job! But it would be more readable if |
Show me how you would prefer it. |
@GetMapping("/author/{id}")
RepresentationModel<?> authorDetails(@PathVariable int id) {
return ModelBuilder
//.root(someObj) possibility to add some fields to the root is missing?
.embed(
LinkRelation.of("author"), // that could be a string
entity(new Author("Alan Watts", "January 6, 1915", "November 16, 1973")), // that could be an Object without call to entity(..)
link(new Link("/people/alan-watts")) // this is varargs as it is optional. also could be a Link without calls to link(..)
)
.embed(
LinkRelation.of("illustrator")),
entity(new Author("John Smith", null, null)),
link(new Link("/people/john-smith"))
)
.link(new Link("/books/the-way-of-zen"))
.link(new Link("/people/alan-watts", LinkRelation.of("author")))
.link(new Link("/people/john-smith", LinkRelation.of("illustrator")))
.build();
} |
That still feels like quite a bit of duplication? What if we started with a Link wattsLink = new Link("/people/alan-watts", LinkRelation.of("author"));
Link illustratorLink = new Link("/people/john-smith", LinkRelation.of("illustrator"));
ModelBuilder.entity(…)
.andLink(wattsLink).withEmbed(new Author(…))
.andLink(illustratorLink).withEmbed(new Author(…))
.build(); That could still keep the |
Can we gather this feedback underneath #864? |
We took a first stab at a HAL specific model builder with 2cab91a. See the updated reference documentation for details. |
Hi,
Google is full of questions around how to create embedded HAL resources of different types inside the main root resource. I looked at the Resources Interface, but that can only be leveraged by same types to model collection of a particular type.
I am currently using Spring-Hateoas to create a nested resource hierarchy and creating "_embedded" jsonproperty looks like a hack. Spring Data Rest has support for embedding entities, so it will be really helpful if you could please create a sample for embedding different type of single and collection of resources within a root resource.
The text was updated successfully, but these errors were encountered: