Previously we registered a special HttpMessageConverter with a custom ObjectMapper to deploy the HAL customizations. That converter was added to Spring MVC registered HandlerAdapters and registered as the first converter.
In case Spring MVC handled a request with Accept header */* or no Accept header at all, this meant that this converter kicked in and served HAL even for objects that don't need the customizations.
We now restrict the applicability of that special HttpMessageConverter to subtypes of ResourceSupport so that it will only be chosen if the object to render is of such type.
We now only lookup the beans, Jackson2ModuleRegisteringBeanPostProcessor needs to post-process other beans if the post-processing is really needed. This avoids premature initialization of those dependent beans.
The Jackson(2)ModuleRegisteringBeanPostProcessor now uses postProcess*Before*Initialization to make sure, afterPropertiesSet() has not been called on the target components which might have propagated the original HttpMessageConverters into other internal components.
With this fix, adding the HttpMessageConverter for HAL is added before the call and thus will be propagated to downstream components.
The LinkDiscoverer interface is now a Plugin<MediaType> to allow selecting a discoverer per media type. We also provide a LinkDiscoverers wrapper around a PluginRegistry for easier injection.
Dropped DefaultLinkDiscoverer as the above mentioned changed prohibits the usage of a discoverer without a media type. Clients that previously used DefaultLinkDiscoverer should switch to JsonPathLinkDiscoverer with a custom JsonPath expression and media type.
@EnableHypermediaSupport now supports multiple HypermediaType values set to be able to set up support for multiple hypermedia formats. Admittedly, the only currently supported type is HAL but we prepare for the addition of other (e.g. Collection/JSON or the like). We changed the infrastructure setup taken care of by @EnableHypermediaSupport to not enrich all ObjectMapper instances with our HAL modules but explicitly register an ObjectMapper with the application context and then registering a custom MappingJackson(2)HttpMessageConverter with the HandlerAdapter instances present in the ApplicationContext. We skip the registration if an already registered MJ2HMC has an ObjectMapper already supporting the Spring HATEOAS mixins.
Removed some compiler warnings.
Introduced CurieProvider interface as well as a DefaultCurieProvider that can be registered as Spring Bean to enable Links being rendered in a curie namespace and an additional curie link exposing the metadata of how to lookup the rel definition.
Deprecated Jackson 1 integration. Added helper class to find out whether a relation type is defined by the IANA.
Added @Relation annotation to be able to define the relations that shall be exposed. The annotation can be used on domain classes or ResourceSupport subtypes to define the relations that shall be used to build links pointing to them.
Introduced RelProvider implementations that use the plain domain class name plus an appended List by default (DefaultRelProvider, fallback) as well as an AnnotationRelProvider that will inspect @Relation on the domain type. Added a DelegatingRelProvider that is based on a Spring Plugin PluginRegistry to allow adding RelProvider implementations transparently. Polished AnnotationRelProvider (added annotation caching) and corrected ControllerRelProvider to lookup relation types from Controller classes. Added BeanDefinition setup to HypermediaSupportBeanDefinitionRegistrar to setup a PluginRegistry of RelProviders and the wrapping DelegatingRelProvider to become the primary auto wiring candidate.
Moved RelProvider registration into Jackson HandlerInstantiator implementations. Made the BeanPostProcessors for Jackson ObjectMapper customization aware of the BeanFactory to lookup the DelegatingRelProvider instance to hand them into the Jackson HandlerInstantiators.
TODOs:
- More tests
- Correctly register ControllerRelProviders
In case no ObjectMapper bean has been configured explicitly, the Spring MVC infrastructure registers HttpMessageConverters directly and does not declare them as Spring beans. Thus we now also inspect RequestMappingHandlerAdapter and AnnotationMethodHandlerAdapter instances for their HttpMessageConverters and transparently augment the ObjectMappers backing potentially registered Jackson converters.
The annotation registers supporting application components as Spring beans based on the configured hypermedia type. Currently supported are the default rendering as well as HAL. We register a matching LinkDiscoverer implementation as well as the appropriate Jackson modules (if present on the classpath) to support HAL.
Upgraded to Spring 3.1.4 to benefit from fix to prevent multiple invocations of ImportBeanDefinitionRegistrars (see SPR-9939 / SPR-9925).
Introduced UriComponentsContributor interface to allow components to enhance the UriComponentsBuilder used while building links point in to controller methods.
Moved logic from ControllerLinkBuilder into ControllerLinkBuilderFactory as we now potentially need access to Spring injected components. Might be necessary to get rid of the static LinkBuilder implementations entirely.
EntityLinks allow accessing LinkBuilders or even Link instance based on components exposing REST resources for a particular domain type. The core implementation is ControllerEntityLinks that assumes a particular URI structure so that it can derive the URIs to be asked for per domain type. The domain type managed will be inspected from the @ExposesResourceFor annotation on a controller class. We provide a factory bean to allow configuring instances of ControllerEntityLinks based on a mapping annotation and LinkBuilderFactory.
Added infrastructure to activate automatic discovery of EntityLinks implementations through @EnableEntityLinks. This will automatically register ControllerEntityLinks instances for Spring MVC controllers annotated with @ExposesResourceFor as well as JAX-RS resources if JAX-RS is on the classpath. The mechanism essentially registers a DelegatingEntityLinks instance leveraging the Spring Plugin PluginRegistry mechanism to delegate to the actual EntityLinks instance actually registered for the entity type. It will become the primary EntityLinks bean in the ApplicationContext so that they can be autowired into client components safely.