#837 - Added section on registering a custom media type.

This commit is contained in:
Oliver Drotbohm
2019-03-02 00:00:31 +01:00
parent fe1cbcad67
commit fc49f3ead4

View File

@@ -56,4 +56,89 @@ Since the purpose of the `CurieProvider` API is to allow for automatic curie cre
[[mediatypes.custom]]
== Registering a custom media type
TODO
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 implementations 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.
[[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:
.An example `MediaTypeConfigurationProvider` declaration
====
[source]
org.springframework.hateoas.config.MediaTypeConfigurationProvider=\
com.acme.mymediatype.MyMediaTypeConfigurationProvider
====
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 the application selected media types to activate passed. This allows the media type implementation to control, when it it will be activated.
====
The configuration class has to implement `HypermediaMappingInformation`. It could look as simple as this:
====
[source, java]
----
@Configuration
class MyMediaTypeConfiguration implements HypermediaMappingInformation {
@Override
public List<MediaType> getMediaTypes() {
return MediaType.parse("application/vnd-acme-media-type") <1>
}
@Override
public Module getJacksonModule() {
return new Jackson2MediaTypeModule(); <2>
}
@Bean
MyLinkDiscoverer myLinkDiscoverer() {
return new MyLinkDiscoverer(); <3>
}
}
----
<1> The configuration class returns the media type it wants to get Spring MVC / Spring WebFlux support set up.
<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.
====
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(…)`.
[[mediatypes.custom.recommendation]]
=== Recommendations
The preferred way to implement media type representations is by providing a type hierarchy that matches the expected format and can be serialized by Jackson as is.
In the `Serializer` and `Deserializer` implementations registered for `RepresentationModel`, convert the instances into the media type specific model types and then lookup the Jackson serializer for those.
The media types supported by default use the same configuration mechanism as third party implementations would.
So it's worth studying the implementations in https://github.com/spring-projects/spring-hateoas/tree/master/src/main/java/org/springframework/hateoas/mediatype[the `mediatype` package].