#47, #60 - Implemented RelProvider registration into HAL serializers.

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
This commit is contained in:
Oliver Gierke
2013-04-15 17:31:08 +02:00
parent 47b50266b8
commit 254339c3b2
15 changed files with 731 additions and 39 deletions

View File

@@ -18,26 +18,28 @@ package org.springframework.hateoas.mvc;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.hateoas.ExposesResourceFor;
import org.springframework.hateoas.RelProvider;
import org.springframework.plugin.core.PluginRegistry;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* @author Oliver Gierke
*/
public class ControllerRelProvider implements RelProvider {
private final Class<?> controllerType;
private final Class<?> entityType;
private final String collectionResourceRel;
private final String singleResourceRel;
private final PluginRegistry<RelProvider, Class<?>> providers;
public ControllerRelProvider(Class<?> controller) {
public ControllerRelProvider(Class<?> controller, PluginRegistry<RelProvider, Class<?>> providers) {
Assert.notNull(controller);
ExposesResourceFor annotation = AnnotationUtils.findAnnotation(controller, ExposesResourceFor.class);
Assert.notNull(annotation);
this.controllerType = controller;
this.entityType = annotation.value();
this.singleResourceRel = StringUtils.uncapitalize(entityType.getSimpleName());
this.collectionResourceRel = singleResourceRel + "List";
this.providers = providers;
}
/*
@@ -45,8 +47,8 @@ public class ControllerRelProvider implements RelProvider {
* @see org.springframework.hateoas.RelProvider#getRelForCollectionResource(java.lang.Class)
*/
@Override
public String getRelForCollectionResource(Class<?> type) {
return collectionResourceRel;
public String getCollectionResourceRelFor(Class<?> resource) {
return providers.getPluginFor(entityType).getCollectionResourceRelFor(resource);
}
/*
@@ -54,7 +56,16 @@ public class ControllerRelProvider implements RelProvider {
* @see org.springframework.hateoas.RelProvider#getRelForSingleResource(java.lang.Class)
*/
@Override
public String getRelForSingleResource(Class<?> type) {
return singleResourceRel;
public String getSingleResourceRelFor(Class<?> resource) {
return providers.getPluginFor(entityType).getSingleResourceRelFor(resource);
}
/*
* (non-Javadoc)
* @see org.springframework.plugin.core.Plugin#supports(java.lang.Object)
*/
@Override
public boolean supports(Class<?> delimiter) {
return controllerType.equals(delimiter);
}
}