-
Notifications
You must be signed in to change notification settings - Fork 476
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
Support customizing additional HAL-FORMS properties #1018
Comments
The thing I’ve tinkered with was whether to create media type specific annotations that allow you to apply such settings or where it makes sense to have vendor neutral options. I’ve also looked at whether you can have one annotation that covers them all vs separate annotation for each one. Given an annotation attribute can NOT have a null value pushes me toward more/smaller annotations. Also need @odrotbohm ‘s opinion as well. |
Some thoughts:
Personally, I'd rather see something that communicates intent rather than a specific output on my resources, and handle mapping to a specific media type through convention (well-known annotations) and configuration. |
I think resource bundles are a great and established tool when it comes to what they were intended for: i18n. That's why the prompts are pulled from that. We unfortunately can't switch to return Generally speaking, JSR-303 seems fine if we assume that dedicated DTOs are used to capture payloads and describe responses. However, the tricky bit is that people usually expect Jackson customizations to work on those, and there has to be a way to keep those in sync. Also, We can always end up adding detailed knobs to the media type specific configuration but I'd rather make this a process based on actual user requirements VS. coming up with ideas from thin air. Here are the immediate steps I'm gonna take:
I'll also have a look at how to integrate the JSR-303 inspections. |
Regarding JSR-303 and dedicated DTOs, how would one return a resource without a "DTO" of some sort? Even if that "DTO" was actually a full-blown heavy-weight class with full business logic, there's still something that is going to get serialized and sent back as the data for the resource. It makes sense to take advantage of any declarative information that is relevant to that media type. Similarly with the read-only. You could infer read-only by the absence of a setter, but if there is a declarative read-only annotation that would take precedence. I'm not familiar enough with Jackson customizations to speak to that -- can you specify a regex pattern with them? (Full disclosure: I've been doing .Net for the last ~20 years with a brief diversion into Java around the time Rod Johnson published Expert One-on-One J2EE Design and Development, and currently I've been working with it for about 5 weeks.) Where I could see an issue is if somebody provided conflicting constraints through both mechanisms, but that's going to cause problems outside HATEOAS, so I think that's outside the scope of what Spring-HATEOAS should handle, other than to have some order of precedence (e.g. if a Jackson constraint is found, stop looking or something like that). In my mind what I'm describing is completely neutral to both the selected media type and the choice of declarative constraints, assuming, of course, that Spring-HATEOAS knows about and supports those constraints. As for an actual user requirement: I need to be able to describe a regex that applies to the allowed values of a data field to the client. At the moment, I happen to be using the HAL-Forms media type. That's it. I don't much care how, as long as it's declarative, easy to understand, and easy to maintain. |
…tation model classes. We now consider additional Jackson and JSR-303 annotations on representation models to enrich the HAL Forms template properties with additional information: - @NotNull on a property flips its `required` flag to `true`. - The "regexp" attribute of @pattern on a property is forwarded into the "regex" field. - @JsonProperty(Access.READ_ONLY) on a property is translated into the "readOnly" flag. The default for the "required" flag have been changed to false even for PUT and POST as whether they're required or not is completely determined by the model, not the HTTP method. All of this is backed by significant refactoring in the way that Affordance instances are build internally. The new API is centered around the Affordances type in the mediatype package. The methods on Link to create the Affordance` from its details have been removed and replaced by builder style APIs on Affordance. AffordanceModelFactory has been moved to the mediatype as well. PropertyUtils has been significantly revamped to expose a PayloadMetadata/PropertyMetadata model to abstract the individual traits of a property. This allows to optionally plug in the support for JSR-303 annotations. AffordanceModelFactory has been refactored to rather work with those instead of ResolvableType.
…tation model classes. We now consider additional Jackson and JSR-303 annotations on representation models to enrich the HAL Forms template properties with additional information: - @NotNull on a property flips its `required` flag to `true`. - The "regexp" attribute of @pattern on a property is forwarded into the "regex" field. - @JsonProperty(Access.READ_ONLY) on a property is translated into the "readOnly" flag. The default for the "required" flag have been changed to false even for PUT and POST as whether they're required or not is completely determined by the model, not the HTTP method. All of this is backed by significant refactoring in the way that Affordance instances are build internally. The new API is centered around the Affordances type in the mediatype package. The methods on Link to create the Affordance` from its details have been removed and replaced by builder style APIs on Affordance. AffordanceModelFactory has been moved to the mediatype as well. PropertyUtils has been significantly revamped to expose a PayloadMetadata/PropertyMetadata model to abstract the individual traits of a property. This allows to optionally plug in the support for JSR-303 annotations. AffordanceModelFactory has been refactored to rather work with those instead of ResolvableType.
The reason I made this distinction in the first place is that in domain types (as opposed to DTOs), JSR-303 is often used to "implement" domain constraints when a value type would've been the better alternative: @Email
String emailAddress; While this is perfectly fine in a DTO, it will probably have to be able to capture invalid values as well to produce proper validation messages, in the context of a domain object as nobody using the EmailAddress emailAddress I went ahead and added the support for JSR-303s Please give the current snapshots a try. We still have one week until RC1 and I'm happy to tweak things further. |
Looks fantastic. Thanks! Could anything around this change have caused rest-messages.properties to no longer work? |
Yes, there was a glitch introduced in the course of the optimizations made for #1019. That should be fixed with the latest commits. The snapshots should be available in a couple of minutes. Would love to hear your feedback as we're shooting for the RC release by the end of the week. |
I'll take a look as soon as I get into the office tomorrow morning (US, Eastern time). Thanks! |
Looks good. Working as expected again. One minor error in the docs: in Example 35 it shows |
Now that we've got support for
prompt
thanks to #979, it would be nice to add support for the remaining "standard" HAL-Forms properties. I did notice that it adds the prompt everywhere using thename
, rather than only adding it when defined. According to the spec, if the prompt is missing, clients MAY act as if it was set to the value ofname
. #979 kind of short-circuits that.Some thoughts:
readOnly
- could use absence of setter to auto-setregex
,required
- Add JSR-303 support to HAL-FORMS #619 suggests using JSR-303, which seems like a clear and elegant solutiontemplated
,value
- honestly, I'm not certain at the moment what these would be used for, so I don't feel qualified to make any suggestionsIt seems easy enough to simply add the rest from a resource bundle, and I briefly considered creating a PR until I remembered the corporate proxy I'm stuck behind that blocks the git protocol, which, in this case, is probably a good thing since I think the solutions above are much more elegant and better for long-term maintenance of the consuming codebase. It might still be beneficial to allow overriding through resources, but I don't know how that fits into the Spring philosophy (I've only just picked up Java again after a 15 year absence and Spring has changed just a little bit since then).
The text was updated successfully, but these errors were encountered: