DATAREST-93 - Refactorings in HandlerAdapters.

Use constructor injection consistently now in ResourceProcessorInvokingHandlerAdapter and RepositoryRestHandlerAdapter. Removed unnecessary constructor in ResourceProcessorInvokingHandlerAdapter.

Renamed RestController annotation to RepositoryRestController to avoid confusion with Spring 4's @RestController.
This commit is contained in:
Oliver Gierke
2013-08-16 12:03:53 +02:00
parent f02b717c44
commit 70443fc6a7
10 changed files with 60 additions and 42 deletions

View File

@@ -29,7 +29,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
* @author Jon Brisbin
* @author Oliver Gierke
*/
@RestController
@RepositoryRestController
public class RepositoryController extends AbstractRepositoryRestController {
private final Repositories repositories;

View File

@@ -65,7 +65,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
* @author Jon Brisbin
* @author Oliver Gierke
*/
@RestController
@RepositoryRestController
class RepositoryEntityController extends AbstractRepositoryRestController implements ApplicationEventPublisherAware {
private static final String BASE_MAPPING = "/{repository}";

View File

@@ -63,7 +63,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
* @author Jon Brisbin
* @author Oliver Gierke
*/
@RestController
@RepositoryRestController
@SuppressWarnings({ "unchecked" })
public class RepositoryPropertyReferenceController extends AbstractRepositoryRestController implements
ApplicationEventPublisherAware {

View File

@@ -24,12 +24,15 @@ import java.lang.annotation.Target;
import org.springframework.stereotype.Component;
/**
* Annotation to demarcate Spring MVC controllers provided by Spring Data REST. Allows to easily detect them and exclude
* them from standard Spring MVC handling.
*
* @author Oliver Gierke
*/
@Documented
@Component
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE, ElementType.ANNOTATION_TYPE })
public @interface RestController {
public @interface RepositoryRestController {
}

View File

@@ -2,8 +2,9 @@ package org.springframework.data.rest.webmvc;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.Ordered;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.hateoas.ResourceProcessor;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
@@ -18,26 +19,50 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl
*/
public class RepositoryRestHandlerAdapter extends ResourceProcessorInvokingHandlerAdapter {
@Autowired private List<HandlerMethodArgumentResolver> argumentResolvers;
private final List<HandlerMethodArgumentResolver> argumentResolvers;
/**
* Creates a new {@link RepositoryRestHandlerAdapter} using the given {@link HandlerMethodArgumentResolver} and
* {@link ResourceProcessor}s.
*
* @param argumentResolvers must not be {@literal null}.
* @param resourceProcessors must not be {@literal null}.
*/
public RepositoryRestHandlerAdapter(List<HandlerMethodArgumentResolver> argumentResolvers,
List<ResourceProcessor<?>> resourceProcessors) {
super(resourceProcessors);
this.argumentResolvers = argumentResolvers;
}
/*
* (non-Javadoc)
* @see org.springframework.data.rest.webmvc.ResourceProcessorInvokingHandlerAdapter#afterPropertiesSet()
*/
@Override
public void afterPropertiesSet() {
setCustomArgumentResolvers(argumentResolvers);
super.afterPropertiesSet();
}
/*
* (non-Javadoc)
* @see org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter#getOrder()
*/
@Override
public int getOrder() {
return Ordered.HIGHEST_PRECEDENCE;
}
/*
* (non-Javadoc)
* @see org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter#supportsInternal(org.springframework.web.method.HandlerMethod)
*/
@Override
protected boolean supportsInternal(HandlerMethod handlerMethod) {
Class<?> controllerType = handlerMethod.getBeanType();
return (RepositoryController.class.isAssignableFrom(controllerType)
|| RepositoryEntityController.class.isAssignableFrom(controllerType)
|| RepositoryPropertyReferenceController.class.isAssignableFrom(controllerType) || RepositorySearchController.class
.isAssignableFrom(controllerType));
}
Class<?> controllerType = handlerMethod.getBeanType();
return AnnotationUtils.findAnnotation(controllerType, RepositoryRestController.class) != null;
}
}

View File

@@ -92,7 +92,7 @@ public class RepositoryRestHandlerMapping extends RequestMappingHandlerMapping {
@Override
protected boolean isHandler(Class<?> beanType) {
return AnnotationUtils.findAnnotation(beanType, RestController.class) != null;
return AnnotationUtils.findAnnotation(beanType, RepositoryRestController.class) != null;
}
@Override

View File

@@ -29,7 +29,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
* @author Jon Brisbin
* @author Oliver Gierke
*/
@RestController
@RepositoryRestController
class RepositorySchemaController {
private static final String BASE_MAPPING = "/{repository}";

View File

@@ -52,7 +52,7 @@ import org.springframework.web.bind.annotation.ResponseBody;
* @author Jon Brisbin
* @author Oliver Gierke
*/
@RestController
@RepositoryRestController
class RepositorySearchController extends AbstractRepositoryRestController {
private static final String SEARCH = "/search";

View File

@@ -21,11 +21,8 @@ import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.hateoas.ResourceProcessor;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.support.WebBindingInitializer;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.HandlerMethodReturnValueHandler;
import org.springframework.web.method.support.HandlerMethodReturnValueHandlerComposite;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;
@@ -47,30 +44,18 @@ public class ResourceProcessorInvokingHandlerAdapter extends RequestMappingHandl
private static final Method RETURN_VALUE_HANDLER_METHOD = ReflectionUtils.findMethod(
ResourceProcessorInvokingHandlerAdapter.class, "getReturnValueHandlers");
@Autowired(required = false)//
private List<ResourceProcessor<?>> resourcesProcessors = new ArrayList<ResourceProcessor<?>>();
private final List<ResourceProcessor<?>> resourcesProcessors;
/**
* Empty constructor to setup a {@link ResourceProcessorInvokingHandlerAdapter}.
*/
public ResourceProcessorInvokingHandlerAdapter() {
}
/**
* Copy constructor to copy configuration of {@link HttpMessageConverter}s, {@link WebBindingInitializer}, custom
* {@link HandlerMethodArgumentResolver}s and custom {@link HandlerMethodReturnValueHandler}s.
* Creates a new {@link ResourceProcessorInvokingHandlerAdapter} with the given {@link ResourceProcessor}s.
*
* @param original must not be {@literal null}.
* @param resourcesProcessors must not be {@literal null}.
*/
public ResourceProcessorInvokingHandlerAdapter(RequestMappingHandlerAdapter original) {
@Autowired(required = false)
public ResourceProcessorInvokingHandlerAdapter(List<ResourceProcessor<?>> resourcesProcessors) {
Assert.notNull(original);
setMessageConverters(original.getMessageConverters());
setWebBindingInitializer(original.getWebBindingInitializer());
setCustomArgumentResolvers(original.getCustomArgumentResolvers());
setCustomReturnValueHandlers(original.getCustomReturnValueHandlers());
Assert.notNull(resourcesProcessors);
this.resourcesProcessors = resourcesProcessors;
}
/*

View File

@@ -17,12 +17,14 @@ package org.springframework.data.rest.webmvc.config;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import org.springframework.beans.factory.ListableBeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.ComponentScan.Filter;
@@ -42,11 +44,11 @@ import org.springframework.data.rest.core.support.DomainObjectMerger;
import org.springframework.data.rest.core.util.UUIDConverter;
import org.springframework.data.rest.webmvc.PersistentEntityResourceAssembler;
import org.springframework.data.rest.webmvc.PersistentEntityResourceHandlerMethodArgumentResolver;
import org.springframework.data.rest.webmvc.RepositoryRestController;
import org.springframework.data.rest.webmvc.RepositoryRestHandlerAdapter;
import org.springframework.data.rest.webmvc.RepositoryRestHandlerMapping;
import org.springframework.data.rest.webmvc.RepositoryRestRequestHandlerMethodArgumentResolver;
import org.springframework.data.rest.webmvc.ResourceMetadataHandlerMethodArgumentResolver;
import org.springframework.data.rest.webmvc.RestController;
import org.springframework.data.rest.webmvc.ServerHttpRequestMethodArgumentResolver;
import org.springframework.data.rest.webmvc.convert.UriListHttpMessageConverter;
import org.springframework.data.rest.webmvc.json.Jackson2DatatypeHelper;
@@ -59,6 +61,7 @@ import org.springframework.data.web.config.HateoasAwareSpringDataWebConfiguratio
import org.springframework.format.support.DefaultFormattingConversionService;
import org.springframework.hateoas.EntityLinks;
import org.springframework.hateoas.RelProvider;
import org.springframework.hateoas.ResourceProcessor;
import org.springframework.http.MediaType;
import org.springframework.http.converter.HttpMessageConverter;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
@@ -83,8 +86,8 @@ import com.fasterxml.jackson.databind.SerializationFeature;
* @author Oliver Gierke
*/
@Configuration
@ComponentScan(basePackageClasses = RestController.class, includeFilters = @Filter(RestController.class),
useDefaultFilters = false)
@ComponentScan(basePackageClasses = RepositoryRestController.class,
includeFilters = @Filter(RepositoryRestController.class), useDefaultFilters = false)
@ImportResource("classpath*:META-INF/spring-data-rest/**/*.xml")
public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebConfiguration {
@@ -94,6 +97,7 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon
RepositoryRestMvcConfiguration.class.getClassLoader());
@Autowired ListableBeanFactory beanFactory;
@Autowired(required = false) List<ResourceProcessor<?>> resourceProcessors = Collections.emptyList();
@Bean
public Repositories repositories() {
@@ -297,6 +301,7 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon
* Special {@link org.springframework.web.servlet.HandlerAdapter} that only recognizes handler methods defined in the
* provided controller classes.
*
* @param resourceProcessors {@link ResourceProcessor}s available in the {@link ApplicationContext}.
* @return
*/
@Bean
@@ -305,9 +310,9 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon
List<HttpMessageConverter<?>> messageConverters = defaultMessageConverters();
configureHttpMessageConverters(messageConverters);
RepositoryRestHandlerAdapter handlerAdapter = new RepositoryRestHandlerAdapter();
RepositoryRestHandlerAdapter handlerAdapter = new RepositoryRestHandlerAdapter(defaultMethodArgumentResolvers(),
resourceProcessors);
handlerAdapter.setMessageConverters(messageConverters);
handlerAdapter.setCustomArgumentResolvers(defaultMethodArgumentResolvers());
return handlerAdapter;
}