We now use the API introduced in Spring Framework 5.2.2 to customize a WebClient to add hypermedia related en- and decoders without dropping customizations potentially made to the WebClient instance.
RestTemplateHateoasConfiguration depends on a shared bean WebConverters (previously WebMvcConverters). As it can safely be used in both WebFlux and WebMVC scenarios (as it only depends on types from spring-web), we now include a declaration in the shared HateoasConfiguration. This also allows us to remove the just introduced explicit declaration of a WebConverter bean in WebFluxHateoasConfiguration.
UriTemplate now uses UriBuilderFactory (DefaultUriBuilderFactory in particular) to expand templates. We inspect the given source URI string, try to decode it and configure the factory to only encode values if the decoded String is shorter than the source one as that indicates it already contains encoded characters.
The UriBuilderFactory is held as transient value as its implementations are usually not serializable in the first place. Added the necessary logic to recreate the factory instance on deserialization.
Added all expansion tests given in the original ticket as unit tests.
RestTemplateHateoasConfiguration previously referred to HypermediaWebMvcConfigurer which is turn depending on WebMvcConfigurer, a type living in spring-webmvc. The very former would still get active in WebFlux as the web stack is selected based on the presence of either DispatcherServlet or DispatcherHandler. This is now resolved by using a WebMvcConverter indrection to handle the configuration tweaks avoiding the reference to interfaces from spring-webmvc.
Introduced an ArchUnit based test that Spring HATEOAS code only depends on Spring types containing references to reactive types from either the ….reactive package or classes starting with WebFlux.
We constrained the RepresentationModel type parameter in a way that non of the RepresentationModel subclasses we provide aren't usable with it. That's now fixed by loosing that restriction to an arbitrary type.
We now use Spring's ConcurrentReferenceHashMap to keep instances of UriTemplate cached but at the same time allow the cache entries to be garbage collected if necessary.
We now explicitly equip the resource bundle base name with a "classpath:" prefix so that the resource lookup also works in Boot web applications in which the ResourceLoader setup is tweaked to prefer ServletContext resources.
We now avoid a double-lookup of the default messages in the resource bundle setup. Tightened the test case to make sure the sample resource bundle is properly used, even if no default messages bundle is present.
With Spring WebFlux properly handling custom codecs, no need to disable the default handlers.
This commit verifies WebFlux configuration in test cases, and also adds an equivalent set of test cases verifying Web MVC configuration as well.
Supercedes: #1047
Clean up code containing various patterns:
* Remove redundant `final`, `public`, and `static` declarations in interfaces and enums.
* Replace redundant `? extends Object` generic parameters with `?`.
* Convert collections to arrays using empty array instead of pre-sized one (modern JVM recommendation).
* Initialize collections using constructor call over `addAll`.
* Favor `addAll` over iterating and adding one-by-one.
* Take advantage of `Map.forEach` that was introduced with Java 8.
We now properly look for resource bundles by scanning for a resource bundle *pattern* instead of a plain file named rest-messages. Added integration tests to make sure that resource bundles are not skipped even if they existed.
Added the ability to define common messages in a rest-default-messages.properties, as Spring Data REST requires that and it would be too cumbersome for Spring Data REST to additionally deploy them in its own configuration.
Introduced MessageResolver interface and moved all components previously referring to MessageSourceResolvable to it. This allows us to directly shortcut message resolution by providing a no-op instance in case our default resource bundle rest-messages does not exist and thus avoid the overhead of attempted message resolutions in that case.
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.
We now clearly separate the beans registered by configuration backing @EnableEntityLinks into the ones that depend on Spring MVC being used and commonly shared ones. Tweaked the setup of @EnableHypermediaSupport to rather include the individual configuration classes instead of using @EnableEntityLinks directly as that would always pull WebMVC specific components.
HalLinkRelation now implements MessageSourceResolvable.getDefaultMessage() returning an empty String to avoid NoSuchMessageExceptions for every resolution not backed by an actual translation. Tweaked serialization configuration for HalLink to not render empty title strings.
HalFormsConfiguration now delegates to a HalConfiguration and the configuration will favor a user registered instance of the former over an instance of the latter or even fall back to default instances in case none of that is defined in the ApplicationContext.
This allows seamless pickup of HalConfiguration for HAL FORMS but also explicit opt-out if not desired.
Prior to this commit the HAL-FORMS implementation verified the URIs of the affordances to match the self link of the representation model. This prevents the implementation of the HAL-FORMS metadata lookup protocol as defined in the HAL-FORMS specification [0].
We removed the verification to allow alternate URIs to be used for the afforances.
[0] https://rwcbook.github.io/hal-forms/#_suggested_process_flow_for_hal_forms_documents
We now support _template.$affordanceName.title expressions in the rest-messages resource bundle to internationalize template titles.
Some minor cleanups in test cases and consistent naming for MessageSourceResolvable implementations.
Related tickets: #979.
We now support defining the prompts to be used for properties via the Spring HATEOAS rest-messages resource bundle. We support global definitions via $propertyName._prompt as well as qualified ones ($packageName.)$typeName.$propertyName._prompt.
We now delay the lookup of RepresentationModelProcessor instances in WebMvcHateoasConfiguration so that the BeanPostProcessor registered does now not trigger eager initialization of downstream beans.