-
Notifications
You must be signed in to change notification settings - Fork 472
Create a dedicated builder for HAL representations #864
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
Comments
per @Sam-Kruglov (#270 (comment)): @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();
} |
per @drdamour (#175 (comment)) overall it seems fine. some comments pulling from how i've used resources:
that's my immediate feedback. |
per @odrotbohm (#270 (comment)) 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 |
My deep desire is for the API to flow like the HAL document itself, which is why I deliberately put |
That's the tricky bit. We will have to abstract from HAL a bit to make this also usable for other media types. Maybe a HAL specific subtype could add further constraints then. |
@gregturn I think it should be reflecting the JSON, that is what we are essentially building. So that is why I suggest putting these inside |
That's deceptive but be reminded that this is not a HAL specific API. |
@odrotbohm regarding your example, your builder makes it so link is mandatory which it shouldn't be, at least for my use cases I didn't need them inside |
Not necessarily. As I explained, there could be other more general methods on it but if you're starting with "Here's a link with a given relation…", it's quite natural to be immediately able to state "Oh, btw. here's the preview for the resource that just mentioned link points to.". |
@odrotbohm I see. So, in your example, |
@odrotbohm and about that being a non-HAL specific API, that would still make sense to put things inside |
I prototyped by trying to make things as flat as possible. It A) makes it easier to code a builder pattern and B) reduces the amount of "deep" reading you must undertake. But I get the point of putting something inside another. It definitely self-groups things. |
@gregturn it would actually make the user write less code, since you can omit some of the |
Agree on user over developer. So I seek maximum readability six months later. |
personally, i don't call it embedded....i use the terminology of a subresource in my resource model. _embedded/embedded is a hal specific concept IMO |
I like the idea having a builder that also supports the concept of sub resources. While I like @odrotbohm's idea of using this as a preview for a link relation, I would suggest also allowing sub resources bound to their parent resources directly and then contain optional links themselves. In HAL it is very common to provide |
Create an enclosing version of the builder.
Make a fluent API that lets you construct various RepresentationModel objects (EntityModel, CollectionModel, or complex embedded).
Create an enclosing version of the builder.
Make a fluent API that lets you construct various RepresentationModel objects (EntityModel, CollectionModel, or complex embedded). Related issue: #193.
Experimenting with the use case from #193 has exposed that my original solutions so far only work when confined to a single domain object type. That's no good. What if you want to capture multiple types into a single representation? So I took all the lessons learned, and rewrote the Also captured tests in both WebMVC and WebFlux, verifying they work in either scenario. (Not surprising given this is REALLY just representation assembly). If this is acceptable, I can also update the reference documentation to illustrate using this new |
Create a basic Model interface with a subinterface called Builder. Implement a DefaultModelBuilder that only focuses on entities and links. This allows building some of the simplest representations that are supported by all formats. Implement a HalModelBuilder that supports the same basic operations but also includes HAL-specific embed() and previewFor() as HAL syntax sugar. By having a basic interface, other media types are free to either A) go along with the default format, or B) implement their own implementation, with mediatype-specific operators.
Defines a basic Model.Builder interface that works for all hypermedia types with option for specific mediatypes to implement a customized version. * Implement a DefaultModelBuilder that only focuses on entities and links. This allows building some of the simplest representations that are supported by all formats. * Implement a HalModelBuilder that supports the same basic operations but also includes HAL-specific embed() and previewFor() as HAL syntax sugar. By having a basic interface, other media types are free to either A) go along with the default format, or B) implement their own implementation, with mediatype-specific operators. Also, introduces a preferredMediaTypes attribute in RepresentationModel so various serializers can warn if the user is attempting to serialize a HAL-specific representation as, say, Collection+JSON. Original pull request: #1273. Related issue: #193.
Defines a basic Model.Builder interface that works for all hypermedia types with option for specific mediatypes to implement a customized version. * Implement a DefaultModelBuilder that only focuses on entities and links. This allows building some of the simplest representations that are supported by all formats. * Implement a HalModelBuilder that supports the same basic operations but also includes HAL-specific embed() and previewFor() as HAL syntax sugar. By having a basic interface, other media types are free to either A) go along with the default format, or B) implement their own implementation, with mediatype-specific operators. Also, introduces a preferredMediaTypes attribute in RepresentationModel so various serializers can warn if the user is attempting to serialize a HAL-specific representation as, say, Collection+JSON. Original pull request: #1273. Related issue: #193.
…els. * Implement a `DefaultModelBuilder` that only focuses on entities and links. This allows building some of the simplest representations that are suppoerted by all formats. * Implement a `HalModelBuilder` that supports the same basic operations but also includes HAL-specific embed() and previewFor() as HAL syntax sugar. `DefaultModelBuilder` allows defining "simple" formats (single-item or collection at an aggregate root). A `builder()` static helper is provided to create an instance of this type. `HalModelBuilder` allows going into HAL-specific details, like `embed()` and `previewFor`, where you can specify an entity AND it's link relation. This results in a representation that will generate an "_embedded" entry. It also marks the `RepresntationModel` object with a HAL/HAL-FORMS "preferredMediaType", allowing other serializers to either log warnings, or fail. Having the interface grants hypermedia authors the ability to create their own customized model builders as they see fit. Also, introduces a preferredMediaTypes attribute in RepresentationModel so various serializers can warn if the user is attempting to serialize a HAL-specific representation as, say, Collection+JSON. Original pull request: #1273. Related issue: #193.
* Implement a `DefaultModelBuilder` that only focuses on entities and links. This allows building some of the simplest representations that are suppoerted by all formats. * Implement a `HalModelBuilder` that supports the same basic operations but also includes HAL-specific embed() and previewFor() as HAL syntax sugar. `DefaultModelBuilder` allows defining "simple" formats (single-item or collection at an aggregate root). A `builder()` static helper is provided to create an instance of this type. `HalModelBuilder` allows going into HAL-specific details, like `embed()` and `previewFor`, where you can specify an entity AND it's link relation. This results in a representation that will generate an "_embedded" entry. It also marks the `RepresntationModel` object with a HAL/HAL-FORMS "preferredMediaType", allowing other serializers to either log warnings, or fail. Having the interface grants hypermedia authors the ability to create their own customized model builders as they see fit. Also, introduces a preferredMediaTypes attribute in RepresentationModel so various serializers can warn if the user is attempting to serialize a HAL-specific representation as, say, Collection+JSON. Original pull request: #1273. Related issue: #193.
Consistently use javascript instead of json for JSON code blocks in the reference documentation.
Consistently use javascript instead of json for JSON code blocks in the reference documentation.
We took a first stab at a HAL specific model builder with 2cab91a. See the updated reference documentation for details. |
@drdamour I'm experimenting on a fluent API to build
RepresentationModel
objects. What do you think of something like this for building an embedded structure like you depicted up above?It yields:
A plain old collection where the embedded link relation is a based on the domain type:
produces
And a single item representation:
produces
Related issue: #175
The text was updated successfully, but these errors were encountered: