#1338 - Backport the adjustment to ref docs about custom media types.

Custom media types do NOT require registering a MediaTypeConfigurationProvider implementation with spring.factories. The reference docs must be updated to illustrate this. Also add to the javadocs so users are properly warned.

Original issue: #1304
This commit is contained in:
Greg L. Turnquist
2020-07-28 14:43:31 -05:00
parent ae1bf18adf
commit 2f7a3024e2
2 changed files with 25 additions and 44 deletions

View File

@@ -636,53 +636,23 @@ locale-specific message bundles and even internationalize the metadata.
[[mediatypes.custom]]
== Registering a custom media type
Spring HATEOAS allows to integrate support for custom media types through a set of SPIs, that third parties can implement.
The building blocks of an such an implementation are:
Spring HATEOAS allows you to integrate custom media types through an SPI.
The building blocks of such an implementation are:
1. Some form of Jackson ObjectMapper customization. In its most simple case that's a Jackson `Module` implementation.
2. A `LinkDiscoverer` implementation so that the client-side support is able to detect links in representations generated.
3. Some configuration infrastructure that will allow Spring HATEOAS to find the custom implementation and pick up its configuration.
1. Some form of Jackson `ObjectMapper` customization. In its most simple case that's a Jackson `Module` implementation.
2. A `LinkDiscoverer` implementation so that the client-side support is able to detect links in representations.
3. A small bit of infrastructure configuration that will allow Spring HATEOAS to find the custom implementation and pick it up.
[[mediatypes.custom.configuration]]
=== Custom media type configuration
Custom media type implementations are picked up through Spring's `SpringFactories` mechanism, similar to the Java `ServiceLoader` API.
Each media type implementation needs to ship with a `spring.factories` in `META-INF` containing an implementation class entry for the `org.springframework.hateoas.config.MediaTypeConfigurationProvider` key:
Custom media type implementations are picked up by Spring HATEOAS by scanning the application context for any implementations of the `HypermediaMappingInformation` interface.
Each media type must implement this interface in order to:
.An example `MediaTypeConfigurationProvider` declaration
====
[source]
org.springframework.hateoas.config.MediaTypeConfigurationProvider=\
com.acme.mymediatype.MyMediaTypeConfigurationProvider
====
* Be applied to <<client.web-client, `WebClient`>>, <<client.web-test-client, `WebTestClient`>>, or <<client.rest-template, `RestTemplate`>> instances.
* Support serving that media type from Spring Web MVC and Spring WebFlux controllers.
That implementation class could then look as follows:
.An example `MediaTypeConfigurationProvider` implementation in `META-INF/spring.factories`
====
[source, java]
----
class MyMediaTypeConfigurationProvider
implements MediaTypeConfigurationProvider {
@Override
public Class<? extends HypermediaMappingInformation> getConfiguration() {
return MyMediaTypeConfiguration.class; <1>
}
@Override
public boolean supportsAny(Collection<MediaType> mediaTypes) {
return mediaTypes.contains(MediaTypes.HAL_JSON); <2>
}
}
----
The configuration class needs to have a default constructor and expose two methods:
<1> A method returning a Spring configuration class that will be included in the application bootstrap when Spring HATEOAS is activated (either implicitly via Spring Boot auto-configuration or via `@EnableHypermediaSupport`).
<2> A callback method that will get passed the application selected media types to activate. This allows the media type implementation to control, when it will be activated.
====
The configuration class has to implement `HypermediaMappingInformation`. It could look as simple as this:
To define your own media type could look as simple as this:
====
[source, java]
@@ -697,7 +667,7 @@ class MyMediaTypeConfiguration implements HypermediaMappingInformation {
@Override
public Module getJacksonModule() {
return new Jackson2MediaTypeModule(); <2>
return new Jackson2MyMediaTypeModule(); <2>
}
@Bean
@@ -706,14 +676,22 @@ class MyMediaTypeConfiguration implements HypermediaMappingInformation {
}
}
----
<1> The configuration class returns the media type it wants to get Spring MVC / Spring WebFlux support set up.
<1> The configuration class returns the media type it supports. This applies to both server-side and client-side scenarios.
<2> It overrides `getJacksonModule()` to provide custom serializers to create the media type specific representations.
<3> It also declares a custom `LinkDiscoverer` implementation for client-side support.
<3> It also declares a custom `LinkDiscoverer` implementation for further client-side support.
====
The Jackson module usually declares `Serializer` and `Deserializer` implementations for the representation model types `RepresentationModel`, `EntityModel`, `CollectionModel` and `PagedModel`.
In case you need further customization of the Jackson `ObjectMapper` (like a custom `HandlerInstantiator`), you can alternatively override `configureObjectMapper(…)`.
[IMPORTANT]
====
Prior versions of reference documentation has mentioned implementing the `MediaTypeConfigurationProvider` interface and registering it with `spring.factories`.
This is NOT necessary.
This SPI is ONLY used for out-of-the-box media types provided by Spring HATEOAS.
Merely implementing the `HypermediaMappingInformation` interface and registering it as a Spring bean is all that's needed.
====
[[mediatypes.custom.recommendation]]
=== Recommendations

View File

@@ -20,9 +20,12 @@ import java.util.Collection;
import org.springframework.http.MediaType;
/**
* SPI to register a media type configuration provider.
* SPI used to register internal media types through spring.factories.
*
* WARNING: Do NOT implement this interface if you are coding a custom media type. See "Custom media type configuration" in the reference docs.
*
* @author Oliver Drotbohm
* @author Greg Turnquist
* @see HypermediaMappingInformation
*/
public interface MediaTypeConfigurationProvider {