diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/RepositoryRestMvcConfiguration.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/RepositoryRestMvcConfiguration.java index a56378f30..505e57c76 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/RepositoryRestMvcConfiguration.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/RepositoryRestMvcConfiguration.java @@ -29,7 +29,6 @@ import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.ObjectProvider; -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; @@ -88,6 +87,7 @@ import org.springframework.data.rest.webmvc.support.PagingAndSortingTemplateVari import org.springframework.data.rest.webmvc.support.RepositoryEntityLinks; import org.springframework.data.util.AnnotatedTypeScanner; import org.springframework.data.util.Lazy; +import org.springframework.data.util.StreamUtils; import org.springframework.data.web.HateoasPageableHandlerMethodArgumentResolver; import org.springframework.data.web.HateoasSortHandlerMethodArgumentResolver; import org.springframework.data.web.config.EnableSpringDataWebSupport; @@ -155,46 +155,42 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon private static final boolean IS_JPA_AVAILABLE = ClassUtils.isPresent("javax.persistence.EntityManager", RepositoryRestMvcConfiguration.class.getClassLoader()); - @Autowired ApplicationContext applicationContext; + private final ApplicationContext applicationContext; + private final ConversionService defaultConversionService; - @Autowired(required = false) List> lookups = Collections.emptyList(); - - @Autowired List> defaultMessageConverters; - - ObjectProvider relProvider; - ObjectProvider curieProvider; - ObjectProvider halConfiguration; - ObjectProvider objectMapper; - ObjectProvider invoker; - ObjectProvider resolver; - ObjectProvider geoModule; - - ConversionService defaultConversionService; - - private final Lazy mapper; + private final ObjectProvider relProvider; + private final ObjectProvider curieProvider; + private final ObjectProvider halConfiguration; + private final ObjectProvider objectMapper; + private final ObjectProvider invoker; + private final ObjectProvider resolver; + private final ObjectProvider geoModule; private final ObjectProvider parser; - private ClassLoader beanClassLoader; + private final Lazy mapper; + private final Lazy>> lookups; + private final Lazy>> defaultMessageConverters; + private final Lazy configurerDelegate; + private final Lazy selfLinkProvider; + private final Lazy persistentEntityArgumentResolver; + private final Lazy repoRequestArgumentResolver; + private final Lazy baseUri; + private final Lazy resourceMappings; + private final Lazy repositories; + private final Lazy resourceMetadataHandlerMethodArgumentResolver; + private final Lazy excerptProjector; + private final Lazy persistentEntities; + private final Lazy backendIdHandlerMethodArgumentResolver; + private final Lazy associationLinks; + private final Lazy enumTranslator; + private final Lazy serverHttpRequestMethodArgumentResolver; + private final Lazy eTagArgumentResolver; + private final Lazy repositoryInvokerFactory; + private final Lazy repositoryRestConfiguration; + private final Lazy pageableResolver; + private final Lazy sortResolver; - private Lazy configurerDelegate; - private Lazy selfLinkProvider; - private Lazy persistentEntityArgumentResolver; - private Lazy repoRequestArgumentResolver; - private Lazy baseUri; - private Lazy resourceMappings; - private Lazy repositories; - private Lazy resourceMetadataHandlerMethodArgumentResolver; - private Lazy excerptProjector; - private Lazy persistentEntities; - private Lazy backendIdHandlerMethodArgumentResolver; - private Lazy associationLinks; - private Lazy enumTranslator; - private Lazy serverHttpRequestMethodArgumentResolver; - private Lazy eTagArgumentResolver; - private Lazy repositoryInvokerFactory; - private Lazy repositoryRestConfiguration; - private Lazy pageableResolver; - private Lazy sortResolver; + private ClassLoader beanClassLoader; public RepositoryRestMvcConfiguration( // ApplicationContext context, // @@ -210,6 +206,7 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon super(context, conversionService); + this.applicationContext = context; this.relProvider = relProvider; this.curieProvider = curieProvider; this.halConfiguration = halConfiguration; @@ -218,6 +215,7 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon this.resolver = resolver; this.geoModule = geoModule; this.parser = parser; + this.defaultConversionService = new DefaultFormattingConversionService(); this.mapper = Lazy.of(() -> { @@ -253,11 +251,10 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon this.serverHttpRequestMethodArgumentResolver = Lazy .of(() -> context.getBean(ServerHttpRequestMethodArgumentResolver.class)); this.eTagArgumentResolver = Lazy.of(() -> context.getBean(ETagArgumentResolver.class)); + this.repositoryInvokerFactory = Lazy.of(() -> new UnwrappingRepositoryInvokerFactory( new DefaultRepositoryInvokerFactory(repositories.get(), defaultConversionService), getEntityLookups())); - this.defaultConversionService = new DefaultFormattingConversionService(); - this.configurerDelegate = Lazy.of(() -> { return new RepositoryRestConfigurerDelegate(context.getBeanProvider(RepositoryRestConfigurer.class) @@ -268,6 +265,11 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon this.repositoryRestConfiguration = Lazy.of(() -> context.getBean(RepositoryRestConfiguration.class)); this.pageableResolver = Lazy.of(() -> context.getBean(HateoasPageableHandlerMethodArgumentResolver.class)); this.sortResolver = Lazy.of(() -> context.getBean(HateoasSortHandlerMethodArgumentResolver.class)); + + // Resolution via ResolvableType needed to make the wildcard assignment work + + this.lookups = beansOfType(context, EntityLookup.class); + this.defaultMessageConverters = beansOfType(context, HttpMessageConverter.class); } /* @@ -747,7 +749,7 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon ExceptionHandlerExceptionResolver er = new ExceptionHandlerExceptionResolver(); er.setCustomArgumentResolvers(defaultMethodArgumentResolvers(selfLinkProvider.get(), persistentEntityArgumentResolver.get(), repoRequestArgumentResolver.get())); - er.setMessageConverters(defaultMessageConverters); + er.setMessageConverters(defaultMessageConverters.get()); configurerDelegate.get().configureExceptionHandlerExceptionResolver(er); @@ -879,7 +881,7 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon List> lookups = new ArrayList<>(); lookups.addAll(repositoryRestConfiguration.get().getEntityLookups(repositories.get())); - lookups.addAll(this.lookups); + lookups.addAll(this.lookups.get()); return lookups; } @@ -990,6 +992,23 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon .forEach(it -> it.customizeResources(registry, repositoryRestConfiguration.get())); } + /** + * Helper to be able to obtain a {@link List} of generic types. Otherwise the assignment from {@code Foo} to + * {@code Foo} doesn't work. + * + * @param + * @param context + * @param type + * @return + */ + @SuppressWarnings("unchecked") + private static Lazy> beansOfType(ApplicationContext context, Class type) { + + return Lazy.of(() -> (List) context.getBeanProvider(type) + .orderedStream() + .collect(StreamUtils.toUnmodifiableList())); + } + private static class ResourceSupportHttpMessageConverter extends TypeConstrainedMappingJackson2HttpMessageConverter implements Ordered {