From 25b88136043c9d055bea759cae4f96894410b101 Mon Sep 17 00:00:00 2001 From: Jon Brisbin Date: Fri, 22 Jun 2012 12:15:25 -0500 Subject: [PATCH] Change configuration to make it easier to integrate with an existing Spring MVC application by implementing special MVC mapping and HanndlerAdapter beans that only recognize Spring Data REST components. --- .../RepositoryExporterHandlerAdapter.java | 39 ++++++++++++++ .../RepositoryExporterHandlerMapping.java | 32 ++++++++++++ .../rest/webmvc/RepositoryRestController.java | 2 - .../RepositoryRestMvcConfiguration.java | 51 ++++++------------- 4 files changed, 87 insertions(+), 37 deletions(-) create mode 100644 spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryExporterHandlerAdapter.java create mode 100644 spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryExporterHandlerMapping.java diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryExporterHandlerAdapter.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryExporterHandlerAdapter.java new file mode 100644 index 000000000..f1f305513 --- /dev/null +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryExporterHandlerAdapter.java @@ -0,0 +1,39 @@ +package org.springframework.data.rest.webmvc; + +import java.util.Arrays; + +import org.springframework.core.Ordered; +import org.springframework.http.MediaType; +import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter; +import org.springframework.web.method.HandlerMethod; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; + +/** + * @author Jon Brisbin + */ +public class RepositoryExporterHandlerAdapter extends RequestMappingHandlerAdapter { + + public RepositoryExporterHandlerAdapter() { + setCustomArgumentResolvers(Arrays.asList( + new ServerHttpRequestMethodArgumentResolver(), + new PagingAndSortingMethodArgumentResolver() + )); + + // Add JSON converter for special Spring Data media type + MappingJacksonHttpMessageConverter json = new MappingJacksonHttpMessageConverter(); + json.setSupportedMediaTypes( + Arrays.asList(MediaType.APPLICATION_JSON, MediaType.valueOf("application/x-spring-data+json")) + ); + getMessageConverters().add(json); + } + + @Override public int getOrder() { + return Ordered.HIGHEST_PRECEDENCE; + } + + @Override protected boolean supportsInternal(HandlerMethod handlerMethod) { + return super.supportsInternal(handlerMethod) + && RepositoryRestController.class.isAssignableFrom(handlerMethod.getBeanType()); + } + +} diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryExporterHandlerMapping.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryExporterHandlerMapping.java new file mode 100644 index 000000000..0aa920263 --- /dev/null +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryExporterHandlerMapping.java @@ -0,0 +1,32 @@ +package org.springframework.data.rest.webmvc; + +import java.util.List; +import javax.persistence.EntityManagerFactory; + +import org.springframework.core.Ordered; +import org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor; +import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping; + +/** + * @author Jon Brisbin + */ +public class RepositoryExporterHandlerMapping extends RequestMappingHandlerMapping { + + private EntityManagerFactory entityManagerFactory; + + public RepositoryExporterHandlerMapping(EntityManagerFactory entityManagerFactory) { + this.entityManagerFactory = entityManagerFactory; + setOrder(Ordered.HIGHEST_PRECEDENCE); + } + + @Override protected boolean isHandler(Class beanType) { + return RepositoryRestController.class.isAssignableFrom(beanType); + } + + @Override protected void extendInterceptors(List interceptors) { + OpenEntityManagerInViewInterceptor omivi = new OpenEntityManagerInViewInterceptor(); + omivi.setEntityManagerFactory(entityManagerFactory); + interceptors.add(omivi); + } + +} diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestController.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestController.java index 17e94acec..6006fb6cf 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestController.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestController.java @@ -65,7 +65,6 @@ import org.springframework.http.ResponseEntity; import org.springframework.http.converter.HttpMessageConverter; import org.springframework.http.converter.HttpMessageNotReadableException; import org.springframework.http.server.ServerHttpRequest; -import org.springframework.stereotype.Controller; import org.springframework.ui.ExtendedModelMap; import org.springframework.ui.Model; import org.springframework.util.Assert; @@ -84,7 +83,6 @@ import org.springframework.web.util.UriComponentsBuilder; /** * @author Jon Brisbin */ -@Controller public class RepositoryRestController extends RepositoryExporterSupport implements ApplicationContextAware, diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestMvcConfiguration.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestMvcConfiguration.java index ecafe05a3..8ae3e1524 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestMvcConfiguration.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestMvcConfiguration.java @@ -11,29 +11,21 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.ImportResource; +import org.springframework.core.Ordered; import org.springframework.data.rest.repository.RepositoryExporter; import org.springframework.data.rest.repository.context.ValidatingRepositoryEventListener; import org.springframework.data.rest.repository.jpa.JpaRepositoryExporter; -import org.springframework.http.MediaType; import org.springframework.http.converter.HttpMessageConverter; -import org.springframework.http.converter.json.MappingJacksonHttpMessageConverter; -import org.springframework.orm.jpa.support.OpenEntityManagerInViewInterceptor; import org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor; -import org.springframework.util.Assert; -import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.ViewResolver; -import org.springframework.web.servlet.config.annotation.EnableWebMvc; -import org.springframework.web.servlet.config.annotation.InterceptorRegistry; -import org.springframework.web.servlet.config.annotation.WebMvcConfigurerAdapter; import org.springframework.web.servlet.view.ContentNegotiatingViewResolver; /** * @author Jon Brisbin */ @Configuration -@EnableWebMvc @ImportResource("classpath*:META-INF/spring-data-rest/**/*-export.xml") -public class RepositoryRestMvcConfiguration extends WebMvcConfigurerAdapter { +public class RepositoryRestMvcConfiguration { ContentNegotiatingViewResolver viewResolver; RepositoryRestController repositoryRestController; @@ -50,39 +42,27 @@ public class RepositoryRestMvcConfiguration extends WebMvcConfigurerAdapter { @Autowired(required = false) ValidatingRepositoryEventListener validatingRepositoryEventListener; - @Override public void addArgumentResolvers(List argumentResolvers) { - argumentResolvers.add(new ServerHttpRequestMethodArgumentResolver()); - argumentResolvers.add(new PagingAndSortingMethodArgumentResolver()); - } + RepositoryExporterHandlerAdapter repositoryExporterHandlerAdapter; + RepositoryExporterHandlerMapping repositoryExporterHandlerMapping; - @Override public void addInterceptors(InterceptorRegistry registry) { - registry.addWebRequestInterceptor(openEntityManagerInViewInterceptor()); - } - - @Bean List> httpMessageConverters() { - Assert.notNull(httpMessageConverters); - - if (httpMessageConverters.isEmpty()) { - MappingJacksonHttpMessageConverter json = new MappingJacksonHttpMessageConverter(); - json.setSupportedMediaTypes( - Arrays.asList(MediaType.APPLICATION_JSON, MediaType.valueOf("application/x-spring-data+json")) - ); - httpMessageConverters.add(json); + @Bean RepositoryExporterHandlerAdapter repositoryExporterHandlerAdapter() { + if (null == repositoryExporterHandlerAdapter) { + repositoryExporterHandlerAdapter = new RepositoryExporterHandlerAdapter(); } + return repositoryExporterHandlerAdapter; + } - return httpMessageConverters; + @Bean RepositoryExporterHandlerMapping repositoryExporterHandlerMapping() { + if (null == repositoryExporterHandlerMapping) { + repositoryExporterHandlerMapping = new RepositoryExporterHandlerMapping(entityManagerFactory); + } + return repositoryExporterHandlerMapping; } @Bean PersistenceAnnotationBeanPostProcessor persistenceAnnotationBeanPostProcessor() { return new PersistenceAnnotationBeanPostProcessor(); } - @Bean OpenEntityManagerInViewInterceptor openEntityManagerInViewInterceptor() { - OpenEntityManagerInViewInterceptor oemiv = new OpenEntityManagerInViewInterceptor(); - oemiv.setEntityManagerFactory(entityManagerFactory); - return oemiv; - } - @Bean JpaRepositoryExporter jpaRepositoryExporter() { if (null == customJpaRepositoryExporter) { return new JpaRepositoryExporter(); @@ -110,6 +90,7 @@ public class RepositoryRestMvcConfiguration extends WebMvcConfigurerAdapter { @Bean ContentNegotiatingViewResolver contentNegotiatingViewResolver() { if (null == viewResolver) { viewResolver = new ContentNegotiatingViewResolver(); + viewResolver.setOrder(Ordered.HIGHEST_PRECEDENCE); Map mediaTypes = new HashMap() {{ put("json", "application/json"); @@ -128,7 +109,7 @@ public class RepositoryRestMvcConfiguration extends WebMvcConfigurerAdapter { if (null == repositoryRestController) { this.repositoryRestController = new RepositoryRestController() .repositoryExporters(Arrays.asList(jpaRepositoryExporter())) - .httpMessageConverters(httpMessageConverters()) + .httpMessageConverters(repositoryExporterHandlerAdapter().getMessageConverters()) .jsonMediaType("application/json"); } return repositoryRestController;