From dbfd43c1a0117b648e2471ee3615ca16cf987117 Mon Sep 17 00:00:00 2001 From: Jon Brisbin Date: Tue, 2 Oct 2012 09:05:21 -0500 Subject: [PATCH] Changes to the order in which ApplicationContexts are loaded, changed package that JavaConfig classes are in to keep them from being picked up by the repository component scanning, split single JavaConfig into separate JPA Repository config and Spring Data REST config classes. --- .../ValidatingRepositoryEventListener.java | 24 +++++- .../webmvc/BaseUriMethodArgumentResolver.java | 6 +- ...agingAndSortingMethodArgumentResolver.java | 13 +-- .../webmvc/RepositoryRestHandlerAdapter.java | 16 ++-- .../RepositoryRestMvcConfiguration.java | 22 ++++- ...rverHttpRequestMethodArgumentResolver.java | 3 +- .../data/rest/webmvc/spec/BaseSpec.groovy | 8 +- .../rest/webmvc/spec/DiscoverySpec.groovy | 2 +- .../data/rest/webmvc/spec/EventsSpec.groovy | 4 + .../webmvc/spec/ResourceProcessorSpec.groovy | 2 +- .../data/rest/test/ApplicationConfig.java | 81 ++++++++++++++++++ ...Config.java => ApplicationRestConfig.java} | 84 +++++++------------ .../RestExporterWebInitializer.java | 10 +-- .../rest/test/webmvc/ChildRepository.java | 2 + .../rest/test/webmvc/ParentRepository.java | 2 + .../data/rest/test/webmvc/Person.java | 4 + .../data/rest/test/webmvc/PersonLoader.java | 64 ++++++-------- .../rest/test/webmvc/PersonValidator.java | 2 +- .../data/rest/test/webmvc/Profile.java | 10 ++- .../spring-data-rest/repositories-export.xml | 22 +---- 20 files changed, 226 insertions(+), 155 deletions(-) create mode 100644 spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/ApplicationConfig.java rename spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/{webmvc/ApplicationConfig.java => ApplicationRestConfig.java} (61%) rename spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/{webmvc => }/RestExporterWebInitializer.java (76%) diff --git a/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/ValidatingRepositoryEventListener.java b/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/ValidatingRepositoryEventListener.java index 067dd8a27..b9f57b2ff 100644 --- a/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/ValidatingRepositoryEventListener.java +++ b/spring-data-rest-repository/src/main/java/org/springframework/data/rest/repository/context/ValidatingRepositoryEventListener.java @@ -120,7 +120,27 @@ public class ValidatingRepositoryEventListener errors = new ValidationErrors(domainType.getSimpleName(), o, repositoryMetadataFor(domainType).entityMetadata()); - Collection validators = this.validators.get(event); + + String eventName = null; + if("beforeSave".equals(event)) { + eventName = "before" + domainType.getSimpleName() + "Save"; + } else if("afterSave".equals(event)) { + eventName = "after" + domainType.getSimpleName() + "Save"; + } else if("beforeLinkSave".equals(event)) { + eventName = "before" + domainType.getSimpleName() + "LinkSave"; + } else if("afterLinkSave".equals(event)) { + eventName = "after" + domainType.getSimpleName() + "LinkSave"; + } else if("beforeDelete".equals(event)) { + eventName = "before" + domainType.getSimpleName() + "Delete"; + } else if("afterDelete".equals(event)) { + eventName = "after" + domainType.getSimpleName() + "Delete"; + } + + if(null == eventName) { + return errors; + } + + Collection validators = this.validators.get(eventName); if(null != validators) { for(Validator v : validators) { if(v.supports(o.getClass())) { @@ -129,10 +149,12 @@ public class ValidatingRepositoryEventListener } } } + if(errors.getErrorCount() > 0) { throw new RepositoryConstraintViolationException(errors); } } + return errors; } diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/BaseUriMethodArgumentResolver.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/BaseUriMethodArgumentResolver.java index 649f7eac4..10259297f 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/BaseUriMethodArgumentResolver.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/BaseUriMethodArgumentResolver.java @@ -3,6 +3,7 @@ package org.springframework.data.rest.webmvc; import java.net.URI; import javax.servlet.http.HttpServletRequest; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.MethodParameter; import org.springframework.data.rest.webmvc.json.JsonSchemaController; import org.springframework.web.bind.support.WebDataBinderFactory; @@ -16,12 +17,9 @@ import org.springframework.web.servlet.support.ServletUriComponentsBuilder; */ public class BaseUriMethodArgumentResolver implements HandlerMethodArgumentResolver { + @Autowired private RepositoryRestConfiguration config; - public BaseUriMethodArgumentResolver(RepositoryRestConfiguration config) { - this.config = config; - } - @Override public boolean supportsParameter(MethodParameter parameter) { return (RepositoryRestController.class.isAssignableFrom(parameter.getDeclaringClass()) || JsonSchemaController.class.isAssignableFrom(parameter.getDeclaringClass())) diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/PagingAndSortingMethodArgumentResolver.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/PagingAndSortingMethodArgumentResolver.java index f32844f49..ab0a9fb7b 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/PagingAndSortingMethodArgumentResolver.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/PagingAndSortingMethodArgumentResolver.java @@ -5,6 +5,7 @@ import java.util.ArrayList; import java.util.List; import javax.servlet.http.HttpServletRequest; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.MethodParameter; import org.springframework.data.domain.PageRequest; import org.springframework.data.domain.Sort; @@ -22,18 +23,12 @@ import org.springframework.web.method.support.ModelAndViewContainer; * * @author Jon Brisbin */ -public class PagingAndSortingMethodArgumentResolver - implements HandlerMethodArgumentResolver { +public class PagingAndSortingMethodArgumentResolver implements HandlerMethodArgumentResolver { private static final int DEFAULT_PAGE = 1; // We're 1-based, not 0-based - private RepositoryRestConfiguration config = RepositoryRestConfiguration.DEFAULT; - - public PagingAndSortingMethodArgumentResolver(RepositoryRestConfiguration config) { - if(null != config) { - this.config = config; - } - } + @Autowired + private RepositoryRestConfiguration config; @Override public boolean supportsParameter(MethodParameter parameter) { return ClassUtils.isAssignable(parameter.getParameterType(), PagingAndSorting.class); diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestHandlerAdapter.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestHandlerAdapter.java index d2e5b2bad..ca87cbd6f 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestHandlerAdapter.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/RepositoryRestHandlerAdapter.java @@ -1,10 +1,12 @@ package org.springframework.data.rest.webmvc; -import java.util.Arrays; +import java.util.List; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.Ordered; import org.springframework.data.rest.webmvc.json.JsonSchemaController; import org.springframework.web.method.HandlerMethod; +import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; /** @@ -17,12 +19,12 @@ import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandl */ public class RepositoryRestHandlerAdapter extends ResourceProcessorInvokingHandlerAdapter { - public RepositoryRestHandlerAdapter(RepositoryRestConfiguration config) { - setCustomArgumentResolvers(Arrays.asList( - new ServerHttpRequestMethodArgumentResolver(), - new BaseUriMethodArgumentResolver(config), - new PagingAndSortingMethodArgumentResolver(config) - )); + @Autowired + private List argumentResolvers; + + @Override public void afterPropertiesSet() { + setCustomArgumentResolvers(argumentResolvers); + super.afterPropertiesSet(); } @Override public int getOrder() { 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 9f08c548a..eb209e004 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 @@ -63,9 +63,11 @@ public class RepositoryRestMvcConfiguration { * @return */ @Bean public JpaRepositoryExporter jpaRepositoryExporter() { - return (null == customJpaRepositoryExporter - ? new JpaRepositoryExporter().setDomainTypeMappings(repositoryRestConfig.getDomainTypeToRepositoryMappings()) - : customJpaRepositoryExporter); + if(null == customJpaRepositoryExporter) { + return new JpaRepositoryExporter(); + } + + return customJpaRepositoryExporter; } /** @@ -125,6 +127,18 @@ public class RepositoryRestMvcConfiguration { return new JsonSchemaController(); } + @Bean public BaseUriMethodArgumentResolver baseUriMethodArgumentResolver() { + return new BaseUriMethodArgumentResolver(); + } + + @Bean public PagingAndSortingMethodArgumentResolver pagingAndSortingMethodArgumentResolver() { + return new PagingAndSortingMethodArgumentResolver(); + } + + @Bean public ServerHttpRequestMethodArgumentResolver serverHttpRequestMethodArgumentResolver() { + return new ServerHttpRequestMethodArgumentResolver(); + } + /** * Special {@link org.springframework.web.servlet.HandlerAdapter} that only recognizes handler methods defined in the * {@link RepositoryRestController} class. @@ -132,7 +146,7 @@ public class RepositoryRestMvcConfiguration { * @return */ @Bean public RepositoryRestHandlerAdapter repositoryExporterHandlerAdapter() { - return new RepositoryRestHandlerAdapter(repositoryRestConfig); + return new RepositoryRestHandlerAdapter(); } /** diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/ServerHttpRequestMethodArgumentResolver.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/ServerHttpRequestMethodArgumentResolver.java index 7413df49f..aace3c21f 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/ServerHttpRequestMethodArgumentResolver.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/ServerHttpRequestMethodArgumentResolver.java @@ -23,8 +23,7 @@ public class ServerHttpRequestMethodArgumentResolver implements HandlerMethodArg public Object resolveArgument(MethodParameter parameter, ModelAndViewContainer mavContainer, NativeWebRequest webRequest, - WebDataBinderFactory binderFactory) - throws Exception { + WebDataBinderFactory binderFactory) throws Exception { return new ServletServerHttpRequest((HttpServletRequest)webRequest.getNativeRequest()); } diff --git a/spring-data-rest-webmvc/src/test/groovy/org/springframework/data/rest/webmvc/spec/BaseSpec.groovy b/spring-data-rest-webmvc/src/test/groovy/org/springframework/data/rest/webmvc/spec/BaseSpec.groovy index 17e17b763..c6610efca 100644 --- a/spring-data-rest-webmvc/src/test/groovy/org/springframework/data/rest/webmvc/spec/BaseSpec.groovy +++ b/spring-data-rest-webmvc/src/test/groovy/org/springframework/data/rest/webmvc/spec/BaseSpec.groovy @@ -3,17 +3,16 @@ package org.springframework.data.rest.webmvc.spec import org.codehaus.jackson.map.ObjectMapper import org.springframework.beans.factory.annotation.Autowired import org.springframework.context.ApplicationContext +import org.springframework.data.rest.test.ApplicationConfig +import org.springframework.data.rest.test.ApplicationRestConfig import org.springframework.data.rest.test.webmvc.Address import org.springframework.data.rest.test.webmvc.AddressRepository -import org.springframework.data.rest.test.webmvc.ApplicationConfig import org.springframework.data.rest.test.webmvc.CustomerRepository import org.springframework.data.rest.test.webmvc.Person import org.springframework.data.rest.test.webmvc.PersonRepository import org.springframework.data.rest.test.webmvc.ProfileRepository -import org.springframework.data.rest.test.webmvc.TestRepositoryEventListener import org.springframework.data.rest.webmvc.RepositoryRestConfiguration import org.springframework.data.rest.webmvc.RepositoryRestController -import org.springframework.data.rest.webmvc.RepositoryRestMvcConfiguration import org.springframework.http.ResponseEntity import org.springframework.http.server.ServletServerHttpRequest import org.springframework.mock.web.MockHttpServletRequest @@ -29,11 +28,10 @@ import static org.springframework.transaction.support.TransactionSynchronization /** * @author Jon Brisbin */ -@ContextConfiguration(classes = [ApplicationConfig, RepositoryRestMvcConfiguration]) +@ContextConfiguration(classes = [ApplicationConfig, ApplicationRestConfig]) abstract class BaseSpec extends Specification { @Autowired ApplicationContext appCtx - @Autowired TestRepositoryEventListener listener @Autowired RepositoryRestConfiguration config @Autowired RepositoryRestController controller @Autowired EntityManagerFactory emf diff --git a/spring-data-rest-webmvc/src/test/groovy/org/springframework/data/rest/webmvc/spec/DiscoverySpec.groovy b/spring-data-rest-webmvc/src/test/groovy/org/springframework/data/rest/webmvc/spec/DiscoverySpec.groovy index dd363481e..3a7e88548 100644 --- a/spring-data-rest-webmvc/src/test/groovy/org/springframework/data/rest/webmvc/spec/DiscoverySpec.groovy +++ b/spring-data-rest-webmvc/src/test/groovy/org/springframework/data/rest/webmvc/spec/DiscoverySpec.groovy @@ -25,7 +25,7 @@ class DiscoverySpec extends BaseSpec { def links = readJson(response).links then: - links.size() == 8 + links.size() == 6 } diff --git a/spring-data-rest-webmvc/src/test/groovy/org/springframework/data/rest/webmvc/spec/EventsSpec.groovy b/spring-data-rest-webmvc/src/test/groovy/org/springframework/data/rest/webmvc/spec/EventsSpec.groovy index c08ded450..013fb477b 100644 --- a/spring-data-rest-webmvc/src/test/groovy/org/springframework/data/rest/webmvc/spec/EventsSpec.groovy +++ b/spring-data-rest-webmvc/src/test/groovy/org/springframework/data/rest/webmvc/spec/EventsSpec.groovy @@ -1,7 +1,9 @@ package org.springframework.data.rest.webmvc.spec +import org.springframework.beans.factory.annotation.Autowired import org.springframework.data.rest.repository.RepositoryConstraintViolationException import org.springframework.data.rest.test.webmvc.Person +import org.springframework.data.rest.test.webmvc.TestRepositoryEventListener import org.springframework.http.HttpStatus /** @@ -9,6 +11,8 @@ import org.springframework.http.HttpStatus */ class EventsSpec extends BaseSpec { + @Autowired TestRepositoryEventListener listener + def "cannot save invalid entity"() { given: diff --git a/spring-data-rest-webmvc/src/test/groovy/org/springframework/data/rest/webmvc/spec/ResourceProcessorSpec.groovy b/spring-data-rest-webmvc/src/test/groovy/org/springframework/data/rest/webmvc/spec/ResourceProcessorSpec.groovy index d69e471f6..a24e3e1c3 100644 --- a/spring-data-rest-webmvc/src/test/groovy/org/springframework/data/rest/webmvc/spec/ResourceProcessorSpec.groovy +++ b/spring-data-rest-webmvc/src/test/groovy/org/springframework/data/rest/webmvc/spec/ResourceProcessorSpec.groovy @@ -1,7 +1,7 @@ package org.springframework.data.rest.webmvc.spec import org.springframework.core.MethodParameter -import org.springframework.data.rest.test.webmvc.ApplicationConfig +import org.springframework.data.rest.test.ApplicationConfig import org.springframework.data.rest.webmvc.RepositoryRestMvcConfiguration import org.springframework.data.rest.webmvc.ResourceProcessorHandlerMethodReturnValueHandler import org.springframework.hateoas.Link diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/ApplicationConfig.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/ApplicationConfig.java new file mode 100644 index 000000000..825effb46 --- /dev/null +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/ApplicationConfig.java @@ -0,0 +1,81 @@ +package org.springframework.data.rest.test; + +import java.io.IOException; +import java.sql.Timestamp; +import java.text.SimpleDateFormat; +import java.util.ArrayList; +import java.util.List; +import javax.persistence.EntityManagerFactory; +import javax.sql.DataSource; + +import org.codehaus.jackson.JsonGenerationException; +import org.codehaus.jackson.JsonGenerator; +import org.codehaus.jackson.Version; +import org.codehaus.jackson.map.Module; +import org.codehaus.jackson.map.SerializerProvider; +import org.codehaus.jackson.map.module.SimpleSerializers; +import org.codehaus.jackson.map.ser.std.SerializerBase; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; +import org.springframework.context.annotation.Configuration; +import org.springframework.core.convert.ConversionService; +import org.springframework.core.convert.converter.Converter; +import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.data.rest.test.webmvc.Person; +import org.springframework.data.rest.test.webmvc.PersonValidator; +import org.springframework.data.rest.test.webmvc.TestRepositoryEventListener; +import org.springframework.format.support.DefaultFormattingConversionService; +import org.springframework.hateoas.Link; +import org.springframework.hateoas.Resource; +import org.springframework.hateoas.ResourceProcessor; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; +import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; +import org.springframework.orm.jpa.JpaDialect; +import org.springframework.orm.jpa.JpaTransactionManager; +import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; +import org.springframework.orm.jpa.vendor.Database; +import org.springframework.orm.jpa.vendor.HibernateJpaDialect; +import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; +import org.springframework.transaction.PlatformTransactionManager; +import org.springframework.transaction.annotation.EnableTransactionManagement; + +/** + * @author Jon Brisbin + */ +@Configuration +@ComponentScan(basePackages = "org.springframework.data.rest.test.webmvc") +@EnableJpaRepositories +@EnableTransactionManagement +public class ApplicationConfig { + + @Bean public DataSource dataSource() { + EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); + return builder.setType(EmbeddedDatabaseType.HSQL).build(); + } + + @Bean public EntityManagerFactory entityManagerFactory() { + HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); + vendorAdapter.setDatabase(Database.HSQL); + vendorAdapter.setGenerateDdl(true); + + LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); + factory.setJpaVendorAdapter(vendorAdapter); + factory.setPackagesToScan(getClass().getPackage().getName()); + factory.setDataSource(dataSource()); + + factory.afterPropertiesSet(); + + return factory.getObject(); + } + + @Bean public JpaDialect jpaDialect() { + return new HibernateJpaDialect(); + } + + @Bean public PlatformTransactionManager transactionManager() { + JpaTransactionManager txManager = new JpaTransactionManager(); + txManager.setEntityManagerFactory(entityManagerFactory()); + return txManager; + } + +} diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/ApplicationConfig.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/ApplicationRestConfig.java similarity index 61% rename from spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/ApplicationConfig.java rename to spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/ApplicationRestConfig.java index 698df3973..232e19af4 100644 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/ApplicationConfig.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/ApplicationRestConfig.java @@ -1,12 +1,10 @@ -package org.springframework.data.rest.test.webmvc; +package org.springframework.data.rest.test; import java.io.IOException; import java.sql.Timestamp; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.List; -import javax.persistence.EntityManagerFactory; -import javax.sql.DataSource; import org.codehaus.jackson.JsonGenerationException; import org.codehaus.jackson.JsonGenerator; @@ -16,71 +14,23 @@ import org.codehaus.jackson.map.SerializerProvider; import org.codehaus.jackson.map.module.SimpleSerializers; import org.codehaus.jackson.map.ser.std.SerializerBase; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; -import org.springframework.context.annotation.Import; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.converter.Converter; -import org.springframework.data.jpa.repository.config.EnableJpaRepositories; +import org.springframework.data.rest.test.webmvc.Person; +import org.springframework.data.rest.test.webmvc.PersonValidator; +import org.springframework.data.rest.test.webmvc.TestRepositoryEventListener; import org.springframework.data.rest.webmvc.RepositoryRestMvcConfiguration; import org.springframework.format.support.DefaultFormattingConversionService; import org.springframework.hateoas.Link; import org.springframework.hateoas.Resource; import org.springframework.hateoas.ResourceProcessor; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder; -import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType; -import org.springframework.orm.jpa.JpaDialect; -import org.springframework.orm.jpa.JpaTransactionManager; -import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; -import org.springframework.orm.jpa.vendor.Database; -import org.springframework.orm.jpa.vendor.HibernateJpaDialect; -import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; -import org.springframework.transaction.PlatformTransactionManager; -import org.springframework.transaction.annotation.EnableTransactionManagement; /** * @author Jon Brisbin */ @Configuration -@Import(RepositoryRestMvcConfiguration.class) -@ComponentScan(basePackageClasses = ApplicationConfig.class) -@EnableJpaRepositories -@EnableTransactionManagement -public class ApplicationConfig { - - @Bean public DataSource dataSource() { - EmbeddedDatabaseBuilder builder = new EmbeddedDatabaseBuilder(); - return builder.setType(EmbeddedDatabaseType.HSQL).build(); - } - - @Bean public EntityManagerFactory entityManagerFactory() { - HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); - vendorAdapter.setDatabase(Database.HSQL); - vendorAdapter.setGenerateDdl(true); - - LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); - factory.setJpaVendorAdapter(vendorAdapter); - factory.setPackagesToScan(getClass().getPackage().getName()); - factory.setDataSource(dataSource()); - - factory.afterPropertiesSet(); - - return factory.getObject(); - } - - @Bean public JpaDialect jpaDialect() { - return new HibernateJpaDialect(); - } - - @Bean public PlatformTransactionManager transactionManager() { - JpaTransactionManager txManager = new JpaTransactionManager(); - txManager.setEntityManagerFactory(entityManagerFactory()); - return txManager; - } - - @Bean public TestRepositoryEventListener testRepositoryEventListener() { - return new TestRepositoryEventListener(); - } +public class ApplicationRestConfig extends RepositoryRestMvcConfiguration { @SuppressWarnings({"unchecked"}) @Bean public ConversionService customConversionService() { @@ -116,6 +66,30 @@ public class ApplicationConfig { }; } + @Bean public TestRepositoryEventListener testRepositoryEventListener() { + return new TestRepositoryEventListener(); + } + + /** + * This validator will be picked up automatically. The default configuration is to look at the bean name + * and figure out what event you're interested in. This validator is interested in 'beforeSave' events + * because the word 'beforeSave' appears in the first part of the bean name. It recognizes: + *

+ * - beforeSave + * - afterSave + * - beforeDelete + * - afterDelete + * - beforeLinkSave + * - afterLinkSave + *

+ * What you put after that doesn't matter, you just need to make the bean name unique, of course. + * + * @return + */ + @Bean public PersonValidator beforePersonSaveValidator() { + return new PersonValidator(); + } + @Bean public Module customModule() { return new Module() { private final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS"); diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/RestExporterWebInitializer.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/RestExporterWebInitializer.java similarity index 76% rename from spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/RestExporterWebInitializer.java rename to spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/RestExporterWebInitializer.java index 9120419c2..a729520c5 100644 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/RestExporterWebInitializer.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/RestExporterWebInitializer.java @@ -1,15 +1,13 @@ -package org.springframework.data.rest.test.webmvc; +package org.springframework.data.rest.test; import javax.servlet.ServletContext; import javax.servlet.ServletException; import javax.servlet.ServletRegistration; -import org.springframework.data.rest.webmvc.RepositoryRestExporterServlet; import org.springframework.web.WebApplicationInitializer; import org.springframework.web.context.ContextLoaderListener; import org.springframework.web.context.support.AnnotationConfigWebApplicationContext; import org.springframework.web.servlet.DispatcherServlet; -import org.springframework.web.servlet.config.annotation.DefaultServletHandlerConfigurer; /** * @author Jon Brisbin @@ -25,12 +23,14 @@ public class RestExporterWebInitializer implements WebApplicationInitializer { servletContext.addListener(new ContextLoaderListener(rootContext)); // Register and map the dispatcher servlet - DispatcherServlet servlet = new RepositoryRestExporterServlet(); + DispatcherServlet servlet = new DispatcherServlet(); + servlet.setContextClass(AnnotationConfigWebApplicationContext.class); + servlet.setContextConfigLocation(ApplicationRestConfig.class.getName()); ServletRegistration.Dynamic dispatcher = servletContext.addServlet("dispatcher", servlet); dispatcher.setLoadOnStartup(1); dispatcher.addMapping("/*"); - new DefaultServletHandlerConfigurer(servletContext).enable(); + //new DefaultServletHandlerConfigurer(servletContext).enable(); } } diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/ChildRepository.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/ChildRepository.java index 1b7ffaeba..d84ed6a8a 100644 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/ChildRepository.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/ChildRepository.java @@ -1,9 +1,11 @@ package org.springframework.data.rest.test.webmvc; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.rest.repository.annotation.RestResource; /** * @author Jon Brisbin */ +@RestResource(exported = false) public interface ChildRepository extends JpaRepository { } diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/ParentRepository.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/ParentRepository.java index 8e30d3272..0bd4ac00f 100644 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/ParentRepository.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/ParentRepository.java @@ -1,9 +1,11 @@ package org.springframework.data.rest.test.webmvc; import org.springframework.data.jpa.repository.JpaRepository; +import org.springframework.data.rest.repository.annotation.RestResource; /** * @author Jon Brisbin */ +@RestResource(exported = false) public interface ParentRepository extends JpaRepository { } diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/Person.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/Person.java index 70711ecd8..8b69bed33 100644 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/Person.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/Person.java @@ -50,6 +50,10 @@ public class Person { this.profiles = profiles; } + public Person(String name) { + this.name = name; + } + public Long getId() { return id; } diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/PersonLoader.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/PersonLoader.java index 9594835bb..a7a62dcd5 100644 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/PersonLoader.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/PersonLoader.java @@ -5,76 +5,60 @@ import java.util.HashMap; import java.util.Map; import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.springframework.transaction.annotation.Transactional; /** * @author Jon Brisbin */ -public class PersonLoader - implements InitializingBean { +@Component +public class PersonLoader implements InitializingBean { + @Autowired private PersonRepository personRepository; + @Autowired private ProfileRepository profileRepository; + @Autowired private AddressRepository addressRepository; - public PersonRepository getPersonRepository() { - return personRepository; - } - - public void setPersonRepository(PersonRepository personRepository) { - this.personRepository = personRepository; - } - - public ProfileRepository getProfileRepository() { - return profileRepository; - } - - public void setProfileRepository(ProfileRepository profileRepository) { - this.profileRepository = profileRepository; - } - - public AddressRepository getAddressRepository() { - return addressRepository; - } - - public void setAddressRepository(AddressRepository addressRepository) { - this.addressRepository = addressRepository; - } - + @Transactional @Override public void afterPropertiesSet() throws Exception { + Person p1 = personRepository.save(new Person("John Doe")); + Map pers1profiles = new HashMap(); - Profile twitter = profileRepository.save(new Profile("twitter", "#!/johndoe")); - Profile fb = profileRepository.save(new Profile("facebook", "/johndoe")); + Profile twitter = profileRepository.save(new Profile("twitter", "#!/johndoe", p1)); + Profile fb = profileRepository.save(new Profile("facebook", "/johndoe", p1)); pers1profiles.put("twitter", twitter); pers1profiles.put("facebook", fb); - - Person p1 = personRepository.save( - new Person( - "John Doe", - pers1profiles - ) - ); + p1.setProfiles(pers1profiles); Address pers1addr = addressRepository.save(new Address(new String[]{"1234 W. 1st St."}, "Univille", "ST", "12345")); p1.setAddresses(Arrays.asList(pers1addr)); + personRepository.save(p1); - Map pers2profiles = new HashMap(); - Profile twitter2 = profileRepository.save(new Profile("twitter", "#!/janedoe")); - Profile fb2 = profileRepository.save(new Profile("facebook", "/janedoe")); - pers2profiles.put("facebook", fb2); - Person p2 = personRepository.save(new Person("Jane Doe", pers2profiles)); + Person p2 = personRepository.save(new Person("Jane Doe")); + + Map pers2profiles = new HashMap(); + Profile twitter2 = profileRepository.save(new Profile("twitter", "#!/janedoe", p2)); + Profile fb2 = profileRepository.save(new Profile("facebook", "/janedoe", p2)); + pers2profiles.put("twitter", twitter2); + pers2profiles.put("facebook", fb2); + p2.setProfiles(pers2profiles); Address pers2addr = addressRepository.save(new Address(new String[]{"1234 E. 2nd St."}, "Univille", "ST", "12345")); p2.setAddresses(Arrays.asList(pers2addr)); + personRepository.save(p2); } diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/PersonValidator.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/PersonValidator.java index c738f9872..5ad826390 100644 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/PersonValidator.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/PersonValidator.java @@ -21,7 +21,7 @@ public class PersonValidator @Override public void validate(Object target, Errors errors) { Person p = (Person)target; - LOG.debug("validating Person " + p); + LOG.debug(" ***** Validating Person " + p); ValidationUtils.rejectIfEmpty(errors, "name", "field.name.required", "Field 'name' cannot be blank."); } diff --git a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/Profile.java b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/Profile.java index 964255605..379d79246 100644 --- a/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/Profile.java +++ b/spring-data-rest-webmvc/src/test/java/org/springframework/data/rest/test/webmvc/Profile.java @@ -3,7 +3,7 @@ package org.springframework.data.rest.test.webmvc; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.Id; -import javax.persistence.OneToOne; +import javax.persistence.ManyToOne; import org.codehaus.jackson.annotate.JsonBackReference; @@ -17,7 +17,7 @@ public class Profile { private String type; private String url; @JsonBackReference - @OneToOne(optional = false) + @ManyToOne(optional = false) private Person person; public Profile() { @@ -28,6 +28,12 @@ public class Profile { this.url = url; } + public Profile(String type, String url, Person person) { + this.type = type; + this.url = url; + this.person = person; + } + public String getType() { return type; } diff --git a/spring-data-rest-webmvc/src/test/resources/META-INF/spring-data-rest/repositories-export.xml b/spring-data-rest-webmvc/src/test/resources/META-INF/spring-data-rest/repositories-export.xml index 6417d0205..db5a71218 100644 --- a/spring-data-rest-webmvc/src/test/resources/META-INF/spring-data-rest/repositories-export.xml +++ b/spring-data-rest-webmvc/src/test/resources/META-INF/spring-data-rest/repositories-export.xml @@ -4,12 +4,14 @@ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> - + + + + p:baseUri-ref="baseUri"> - - -