From 97373661744fc15019f93bceb0270975439e5f27 Mon Sep 17 00:00:00 2001 From: "Greg L. Turnquist" Date: Wed, 19 Aug 2020 09:01:33 -0500 Subject: [PATCH] DATAREST-1545 - Migrate away from proxy-based configuration. --- .../ProjectionDefinitionConfiguration.java | 2 +- .../HalExplorerIntegrationTests.java | 61 ++- .../RepositoryRestConfigurerDelegate.java | 2 +- .../RepositoryRestMvcConfiguration.java | 470 +++++++++++------- 4 files changed, 352 insertions(+), 183 deletions(-) diff --git a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/config/ProjectionDefinitionConfiguration.java b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/config/ProjectionDefinitionConfiguration.java index d4732b7ad..1b74642ac 100644 --- a/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/config/ProjectionDefinitionConfiguration.java +++ b/spring-data-rest-core/src/main/java/org/springframework/data/rest/core/config/ProjectionDefinitionConfiguration.java @@ -44,7 +44,7 @@ public class ProjectionDefinitionConfiguration implements ProjectionDefinitions * Creates a new {@link ProjectionDefinitionConfiguration}. */ public ProjectionDefinitionConfiguration() { - this.projectionDefinitions = new HashSet(); + this.projectionDefinitions = new HashSet<>(); } /* diff --git a/spring-data-rest-hal-explorer/src/test/java/org/springframework/data/rest/webmvc/halexplorer/HalExplorerIntegrationTests.java b/spring-data-rest-hal-explorer/src/test/java/org/springframework/data/rest/webmvc/halexplorer/HalExplorerIntegrationTests.java index 71e89d096..02a39b7e5 100755 --- a/spring-data-rest-hal-explorer/src/test/java/org/springframework/data/rest/webmvc/halexplorer/HalExplorerIntegrationTests.java +++ b/spring-data-rest-hal-explorer/src/test/java/org/springframework/data/rest/webmvc/halexplorer/HalExplorerIntegrationTests.java @@ -19,18 +19,25 @@ import static org.hamcrest.CoreMatchers.*; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; +import java.util.Optional; + import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; +import org.springframework.beans.BeansException; import org.springframework.beans.factory.ObjectFactory; +import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.convert.ConversionService; +import org.springframework.data.geo.GeoModule; import org.springframework.data.rest.webmvc.config.RepositoryRestConfigurer; import org.springframework.data.rest.webmvc.config.RepositoryRestMvcConfiguration; import org.springframework.hateoas.MediaTypes; +import org.springframework.hateoas.mediatype.MessageResolver; +import org.springframework.hateoas.server.mvc.RepresentationModelProcessorInvoker; import org.springframework.http.HttpHeaders; import org.springframework.http.MediaType; import org.springframework.test.context.ContextConfiguration; @@ -41,6 +48,8 @@ import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.servlet.config.annotation.EnableWebMvc; +import com.fasterxml.jackson.databind.ObjectMapper; + /** * Integration tests for {@link HalExplorer}. * @@ -61,7 +70,10 @@ public class HalExplorerIntegrationTests { static class TestConfiguration extends RepositoryRestMvcConfiguration { public TestConfiguration(ApplicationContext context, ObjectFactory conversionService) { - super(context, conversionService); + + super(context, conversionService, Optional.empty(), Optional.empty(), Optional.empty(), + new ObjectMapperProvider(), new RepresentationModelProcessorInvokerProvider(), MessageResolver.DEFAULTS_ONLY, + new GeoModule()); } @Bean @@ -119,4 +131,51 @@ public class HalExplorerIntegrationTests { andExpect(status().isOk()).// andExpect(header().string(HttpHeaders.CONTENT_TYPE, startsWith(MediaType.APPLICATION_JSON_VALUE))); } + + private static class ObjectMapperProvider implements ObjectProvider { + + @Override + public ObjectMapper getObject(Object... args) throws BeansException { + return null; + } + + @Override + public ObjectMapper getIfAvailable() throws BeansException { + return null; + } + + @Override + public ObjectMapper getIfUnique() throws BeansException { + return null; + } + + @Override + public ObjectMapper getObject() throws BeansException { + return null; + } + } + + private static class RepresentationModelProcessorInvokerProvider + implements ObjectProvider { + + @Override + public RepresentationModelProcessorInvoker getObject(Object... args) throws BeansException { + return null; + } + + @Override + public RepresentationModelProcessorInvoker getIfAvailable() throws BeansException { + return null; + } + + @Override + public RepresentationModelProcessorInvoker getIfUnique() throws BeansException { + return null; + } + + @Override + public RepresentationModelProcessorInvoker getObject() throws BeansException { + return null; + } + } } diff --git a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/RepositoryRestConfigurerDelegate.java b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/RepositoryRestConfigurerDelegate.java index 5f665497c..9cbe470a1 100644 --- a/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/RepositoryRestConfigurerDelegate.java +++ b/spring-data-rest-webmvc/src/main/java/org/springframework/data/rest/webmvc/config/RepositoryRestConfigurerDelegate.java @@ -34,7 +34,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; * @author Oliver Gierke * @soundtrack Florian Reichelt & Max Ender - Abschlusskonzert (https://www.youtube.com/watch?v=5WP0P-ndinY) */ -class RepositoryRestConfigurerDelegate implements RepositoryRestConfigurer { +public class RepositoryRestConfigurerDelegate implements RepositoryRestConfigurer { private final Iterable delegates; 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 9916b3337..a2dff5732 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 @@ -26,7 +26,6 @@ import java.util.Set; import org.springframework.beans.factory.BeanClassLoaderAware; import org.springframework.beans.factory.BeanFactoryUtils; -import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.ObjectFactory; import org.springframework.beans.factory.ObjectProvider; import org.springframework.beans.factory.annotation.Autowired; @@ -70,12 +69,32 @@ import org.springframework.data.rest.core.support.EntityLookup; import org.springframework.data.rest.core.support.RepositoryRelProvider; import org.springframework.data.rest.core.support.SelfLinkProvider; import org.springframework.data.rest.core.support.UnwrappingRepositoryInvokerFactory; -import org.springframework.data.rest.webmvc.*; +import org.springframework.data.rest.webmvc.BasePathAwareController; +import org.springframework.data.rest.webmvc.BasePathAwareHandlerMapping; +import org.springframework.data.rest.webmvc.BaseUri; +import org.springframework.data.rest.webmvc.EmbeddedResourcesAssembler; +import org.springframework.data.rest.webmvc.HttpHeadersPreparer; +import org.springframework.data.rest.webmvc.ProfileResourceProcessor; +import org.springframework.data.rest.webmvc.RepositoryRestController; +import org.springframework.data.rest.webmvc.RepositoryRestExceptionHandler; +import org.springframework.data.rest.webmvc.RepositoryRestHandlerAdapter; +import org.springframework.data.rest.webmvc.RepositoryRestHandlerMapping; +import org.springframework.data.rest.webmvc.RestMediaTypes; +import org.springframework.data.rest.webmvc.ServerHttpRequestMethodArgumentResolver; import org.springframework.data.rest.webmvc.alps.AlpsJsonHttpMessageConverter; import org.springframework.data.rest.webmvc.alps.RootResourceInformationToAlpsDescriptorConverter; import org.springframework.data.rest.webmvc.convert.UriListHttpMessageConverter; -import org.springframework.data.rest.webmvc.json.*; +import org.springframework.data.rest.webmvc.json.DomainObjectReader; +import org.springframework.data.rest.webmvc.json.EnumTranslator; +import org.springframework.data.rest.webmvc.json.Jackson2DatatypeHelper; +import org.springframework.data.rest.webmvc.json.JacksonMappingAwareSortTranslator; +import org.springframework.data.rest.webmvc.json.JacksonSerializers; +import org.springframework.data.rest.webmvc.json.MappingAwareDefaultedPageableArgumentResolver; +import org.springframework.data.rest.webmvc.json.MappingAwarePageableArgumentResolver; +import org.springframework.data.rest.webmvc.json.MappingAwareSortArgumentResolver; +import org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module; import org.springframework.data.rest.webmvc.json.PersistentEntityJackson2Module.LookupObjectSerializer; +import org.springframework.data.rest.webmvc.json.PersistentEntityToJsonSchemaConverter; import org.springframework.data.rest.webmvc.json.PersistentEntityToJsonSchemaConverter.ValueTypeSchemaPropertyCustomizerFactory; import org.springframework.data.rest.webmvc.mapping.Associations; import org.springframework.data.rest.webmvc.mapping.LinkCollector; @@ -94,7 +113,6 @@ import org.springframework.data.util.AnnotatedTypeScanner; import org.springframework.data.util.Lazy; import org.springframework.data.web.HateoasPageableHandlerMethodArgumentResolver; import org.springframework.data.web.HateoasSortHandlerMethodArgumentResolver; -import org.springframework.data.web.PageableHandlerMethodArgumentResolver; import org.springframework.data.web.config.EnableSpringDataWebSupport; import org.springframework.data.web.config.HateoasAwareSpringDataWebConfiguration; import org.springframework.data.web.config.SpringDataJacksonConfiguration; @@ -128,7 +146,6 @@ import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry import org.springframework.web.servlet.handler.AbstractHandlerMapping; import org.springframework.web.servlet.mvc.method.annotation.ExceptionHandlerExceptionResolver; import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter; -import org.springframework.web.servlet.mvc.method.annotation.ResponseBodyAdvice; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.Module; @@ -148,14 +165,14 @@ import com.fasterxml.jackson.datatype.jdk8.Jdk8Module; * @author Greg Turnquist * @author Mark Paluch */ -@Configuration +@Configuration(proxyBeanMethods = false) @EnableHypermediaSupport(type = HypermediaType.HAL) @ComponentScan(basePackageClasses = RepositoryRestController.class, includeFilters = @Filter(BasePathAwareController.class), useDefaultFilters = false) @ImportResource("classpath*:META-INF/spring-data-rest/**/*.xml") @Import({ SpringDataJacksonConfiguration.class, EnableSpringDataWebSupport.QuerydslActivator.class }) public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebConfiguration - implements InitializingBean, BeanClassLoaderAware { + implements BeanClassLoaderAware { private static final boolean IS_JPA_AVAILABLE = ClassUtils.isPresent("javax.persistence.EntityManager", RepositoryRestMvcConfiguration.class.getClassLoader()); @@ -166,34 +183,113 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon @Autowired(required = false) List configurers = Collections.emptyList(); @Autowired(required = false) List> lookups = Collections.emptyList(); - @Autowired Optional relProvider; - @Autowired Optional curieProvider; - @Autowired Optional halConfiguration; - @Autowired ObjectProvider objectMapper; - @Autowired ObjectProvider invoker; - @Autowired MessageResolver resolver; + @Autowired List> defaultMessageConverters; + + Optional relProvider; + Optional curieProvider; + Optional halConfiguration; + ObjectProvider objectMapper; + ObjectProvider invoker; + MessageResolver resolver; + GeoModule geoModule; + ConversionService defaultConversionService; private final Lazy mapper; - private RepositoryRestConfigurerDelegate configurerDelegate; private ClassLoader beanClassLoader; - public RepositoryRestMvcConfiguration(ApplicationContext context, - @Qualifier("mvcConversionService") ObjectFactory conversionService) { + private Lazy configurerDelegate; + private Lazy selfLinkProvider; + private Lazy persistentEntityArgumentResolver; + private Lazy repoRequestArgumentResolver; + private Lazy baseUri; + private Lazy resourceMappings; + private Lazy repositories; + private Lazy restHandlerMapping; + 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 metadataConfiguration; + private Lazy repositoryRestConfiguration; + private Lazy pageableResolver; + private Lazy sortResolver; + + public RepositoryRestMvcConfiguration( // + ApplicationContext context, // + @Qualifier("mvcConversionService") ObjectFactory conversionService, // + Optional relProvider, // + Optional curieProvider, // + Optional halConfiguration, // + ObjectProvider objectMapper, // + ObjectProvider invoker, // + MessageResolver resolver, // + GeoModule geoModule) { super(context, conversionService); + this.relProvider = relProvider; + this.curieProvider = curieProvider; + this.halConfiguration = halConfiguration; + this.objectMapper = objectMapper; + this.invoker = invoker; + this.resolver = resolver; + this.geoModule = geoModule; + this.mapper = Lazy.of(() -> { Jdk8Module jdk8Module = new Jdk8Module(); jdk8Module.configureAbsentsAsNulls(true); ObjectMapper mapper = basicObjectMapper(); - mapper.registerModule(persistentEntityJackson2Module()); + + LinkCollector linkCollector = context.getBean(LinkCollector.class); + + mapper.registerModule(persistentEntityJackson2Module(linkCollector)); mapper.registerModule(jdk8Module); return mapper; }); + + this.selfLinkProvider = Lazy.of(() -> context.getBean(SelfLinkProvider.class)); + this.persistentEntityArgumentResolver = Lazy + .of(() -> context.getBean(PersistentEntityResourceHandlerMethodArgumentResolver.class)); + this.repoRequestArgumentResolver = Lazy + .of(() -> context.getBean(RootResourceInformationHandlerMethodArgumentResolver.class)); + this.baseUri = Lazy.of(() -> context.getBean(BaseUri.class)); + this.resourceMappings = Lazy.of(() -> context.getBean(RepositoryResourceMappings.class)); + this.repositories = Lazy.of(() -> context.getBean(Repositories.class)); + this.restHandlerMapping = Lazy.of(() -> context.getBean("restHandlerMapping", AbstractHandlerMapping.class)); + this.resourceMetadataHandlerMethodArgumentResolver = Lazy + .of(() -> context.getBean(ResourceMetadataHandlerMethodArgumentResolver.class)); + this.excerptProjector = Lazy.of(() -> context.getBean(ExcerptProjector.class)); + this.persistentEntities = Lazy.of(() -> context.getBean(PersistentEntities.class)); + this.backendIdHandlerMethodArgumentResolver = Lazy + .of(() -> context.getBean(BackendIdHandlerMethodArgumentResolver.class)); + this.associationLinks = Lazy.of(() -> context.getBean(Associations.class)); + this.enumTranslator = Lazy.of(() -> context.getBean(EnumTranslator.class)); + 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.metadataConfiguration = Lazy.of(() -> context.getBean(MetadataConfiguration.class)); + + this.defaultConversionService = new DefaultFormattingConversionService(); + this.configurerDelegate = Lazy.of(() -> context.getBean(RepositoryRestConfigurerDelegate.class)); + this.repositoryRestConfiguration = Lazy.of(() -> context.getBean(RepositoryRestConfiguration.class)); + this.pageableResolver = Lazy.of(() -> context.getBean(HateoasPageableHandlerMethodArgumentResolver.class)); + this.sortResolver = Lazy.of(() -> context.getBean(HateoasSortHandlerMethodArgumentResolver.class)); + } + + @Bean + public static RepositoryRestConfigurerDelegate configurerDelegate(List configurers) { + return new RepositoryRestConfigurerDelegate(configurers); } /* @@ -205,15 +301,6 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon this.beanClassLoader = classLoader; } - /* - * (non-Javadoc) - * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet() - */ - @Override - public void afterPropertiesSet() throws Exception { - this.configurerDelegate = new RepositoryRestConfigurerDelegate(configurers); - } - @Bean public Repositories repositories() { return new Repositories(applicationContext); @@ -227,7 +314,7 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon @Bean public PersistentEntities persistentEntities() { - List> arrayList = new ArrayList>(); + List> arrayList = new ArrayList<>(); for (MappingContext context : BeanFactoryUtils .beansOfTypeIncludingAncestors(applicationContext, MappingContext.class).values()) { @@ -239,11 +326,15 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon @Bean @Qualifier - public DefaultFormattingConversionService defaultConversionService() { + public DefaultFormattingConversionService defaultConversionService(PersistentEntities persistentEntities, + RepositoryInvokerFactory repositoryInvokerFactory, Repositories repositories, + RepositoryRestConfigurerDelegate configurerDelegate) { + + DefaultFormattingConversionService conversionService = (DefaultFormattingConversionService) defaultConversionService; - DefaultFormattingConversionService conversionService = new DefaultFormattingConversionService(); // Add Spring Data Commons formatters - conversionService.addConverter(uriToEntityConverter(conversionService)); + conversionService + .addConverter(new UriToEntityConverter(persistentEntities, repositoryInvokerFactory, repositories)); conversionService.addConverter(StringToLdapNameConverter.INSTANCE); addFormatters(conversionService); @@ -257,8 +348,8 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon * {@link org.springframework.validation.Validator} instances assigned to specific domain types. */ @Bean - public ValidatingRepositoryEventListener validatingRepositoryEventListener( - ObjectFactory entities) { + public ValidatingRepositoryEventListener validatingRepositoryEventListener(ObjectFactory entities, + RepositoryRestConfigurerDelegate configurerDelegate) { ValidatingRepositoryEventListener listener = new ValidatingRepositoryEventListener(entities); configurerDelegate.configureValidatingRepositoryEventListener(listener); @@ -268,6 +359,7 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon @Bean public JpaHelper jpaHelper() { + if (IS_JPA_AVAILABLE) { return new JpaHelper(); } else { @@ -284,15 +376,16 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon ProjectionDefinitionConfiguration configuration = new ProjectionDefinitionConfiguration(); // Register projections found in packages - for (Class projection : getProjections(repositories())) { + for (Class projection : getProjections(repositories.get())) { configuration.addProjection(projection); } RepositoryCorsRegistry registry = new RepositoryCorsRegistry(); WebMvcRepositoryRestConfiguration config = new WebMvcRepositoryRestConfiguration(configuration, - metadataConfiguration(), enumTranslator(), registry); - configurerDelegate.configureRepositoryRestConfiguration(config, registry); + new MetadataConfiguration(), new EnumTranslator(MessageResolver.DEFAULTS_ONLY), registry); + + configurerDelegate.get().configureRepositoryRestConfiguration(config, registry); return (T) config; } @@ -309,8 +402,8 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon } @Bean - public BaseUri baseUri() { - return new BaseUri(repositoryRestConfiguration().getBasePath()); + public BaseUri baseUri(RepositoryRestConfiguration repositoryRestConfiguration) { + return new BaseUri(repositoryRestConfiguration.getBasePath()); } /** @@ -320,7 +413,7 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon * @return */ @Bean - public static AnnotatedEventHandlerInvoker annotatedEventHandlerInvoker() { + public AnnotatedEventHandlerInvoker annotatedEventHandlerInvoker() { return new AnnotatedEventHandlerInvoker(); } @@ -341,32 +434,37 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon * @return */ @Bean - public RootResourceInformationHandlerMethodArgumentResolver repoRequestArgumentResolver() { + public RootResourceInformationHandlerMethodArgumentResolver repoRequestArgumentResolver(Repositories repositories, + ResourceMetadataHandlerMethodArgumentResolver resourceMetadataHandlerMethodArgumentResolver, + @Qualifier RepositoryInvokerFactory repositoryInvokerFactory) { if (QuerydslUtils.QUERY_DSL_PRESENT) { QuerydslBindingsFactory factory = applicationContext.getBean(QuerydslBindingsFactory.class); - QuerydslPredicateBuilder predicateBuilder = new QuerydslPredicateBuilder(defaultConversionService(), + QuerydslPredicateBuilder predicateBuilder = new QuerydslPredicateBuilder(defaultConversionService, factory.getEntityPathResolver()); - return new QuerydslAwareRootResourceInformationHandlerMethodArgumentResolver(repositories(), - repositoryInvokerFactory(defaultConversionService()), resourceMetadataHandlerMethodArgumentResolver(), - predicateBuilder, factory); + return new QuerydslAwareRootResourceInformationHandlerMethodArgumentResolver(repositories, + repositoryInvokerFactory, resourceMetadataHandlerMethodArgumentResolver, predicateBuilder, factory); } - return new RootResourceInformationHandlerMethodArgumentResolver(repositories(), - repositoryInvokerFactory(defaultConversionService()), resourceMetadataHandlerMethodArgumentResolver()); + return new RootResourceInformationHandlerMethodArgumentResolver(repositories, repositoryInvokerFactory, + resourceMetadataHandlerMethodArgumentResolver); } @Bean - public ResourceMetadataHandlerMethodArgumentResolver resourceMetadataHandlerMethodArgumentResolver() { - return new ResourceMetadataHandlerMethodArgumentResolver(repositories(), resourceMappings(), baseUri()); + public ResourceMetadataHandlerMethodArgumentResolver resourceMetadataHandlerMethodArgumentResolver( + Repositories repositories, RepositoryResourceMappings resourceMappings, BaseUri baseUri) { + return new ResourceMetadataHandlerMethodArgumentResolver(repositories, resourceMappings, baseUri); } @Bean - public BackendIdHandlerMethodArgumentResolver backendIdHandlerMethodArgumentResolver() { - return new BackendIdHandlerMethodArgumentResolver(backendIdConverterRegistry(), - resourceMetadataHandlerMethodArgumentResolver(), baseUri()); + public BackendIdHandlerMethodArgumentResolver backendIdHandlerMethodArgumentResolver( + PluginRegistry> backendIdConverterRegistry, + ResourceMetadataHandlerMethodArgumentResolver resourceMetadataHandlerMethodArgumentResolver, BaseUri baseUri) { + + return new BackendIdHandlerMethodArgumentResolver(backendIdConverterRegistry, + resourceMetadataHandlerMethodArgumentResolver, baseUri); } @Bean @@ -382,13 +480,16 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon * @throws Exception */ @Bean - public RepositoryEntityLinks entityLinks() { + public RepositoryEntityLinks entityLinks(HateoasPageableHandlerMethodArgumentResolver pageableResolver, + Repositories repositories, RepositoryResourceMappings resourceMappings, + PluginRegistry> backendIdConverterRegistry, + RepositoryRestConfiguration repositoryRestConfiguration, HateoasSortHandlerMethodArgumentResolver sortResolver) { PagingAndSortingTemplateVariables templateVariables = new ArgumentResolverPagingAndSortingTemplateVariables( - pageableResolver(), sortResolver()); + pageableResolver, sortResolver); - return new RepositoryEntityLinks(repositories(), resourceMappings(), repositoryRestConfiguration(), - templateVariables, backendIdConverterRegistry()); + return new RepositoryEntityLinks(repositories, resourceMappings, repositoryRestConfiguration, templateVariables, + backendIdConverterRegistry); } /** @@ -397,13 +498,17 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon * @return */ @Bean - public PersistentEntityResourceHandlerMethodArgumentResolver persistentEntityArgumentResolver() { + public PersistentEntityResourceHandlerMethodArgumentResolver persistentEntityArgumentResolver( + @Qualifier("defaultMessageConverters") List> defaultMessageConverters, + RootResourceInformationHandlerMethodArgumentResolver repoRequestArgumentResolver, Associations associationLinks, + BackendIdHandlerMethodArgumentResolver backendIdHandlerMethodArgumentResolver, + PersistentEntities persistentEntities) { PluginRegistry, Class> lookups = PluginRegistry.of(getEntityLookups()); - return new PersistentEntityResourceHandlerMethodArgumentResolver(defaultMessageConverters(), - repoRequestArgumentResolver(), backendIdHandlerMethodArgumentResolver(), - new DomainObjectReader(persistentEntities(), associationLinks()), lookups); + return new PersistentEntityResourceHandlerMethodArgumentResolver(defaultMessageConverters, + repoRequestArgumentResolver, backendIdHandlerMethodArgumentResolver, + new DomainObjectReader(persistentEntities, associationLinks), lookups); } /** @@ -412,11 +517,12 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon * @return */ @Bean - public PersistentEntityToJsonSchemaConverter jsonSchemaConverter() { + public PersistentEntityToJsonSchemaConverter jsonSchemaConverter(PersistentEntities persistentEntities, + Associations associationLinks, @Qualifier RepositoryInvokerFactory repositoryInvokerFactory, + RepositoryRestConfiguration repositoryRestConfiguration) { - return new PersistentEntityToJsonSchemaConverter(persistentEntities(), associationLinks(), resolver, objectMapper(), - repositoryRestConfiguration(), - new ValueTypeSchemaPropertyCustomizerFactory(repositoryInvokerFactory(defaultConversionService()))); + return new PersistentEntityToJsonSchemaConverter(persistentEntities, associationLinks, resolver, objectMapper(), + repositoryRestConfiguration, new ValueTypeSchemaPropertyCustomizerFactory(repositoryInvokerFactory)); } /** @@ -434,16 +540,17 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon * @return */ @Bean - public TypeConstrainedMappingJackson2HttpMessageConverter jacksonHttpMessageConverter() { + public TypeConstrainedMappingJackson2HttpMessageConverter jacksonHttpMessageConverter( + RepositoryRestConfiguration repositoryRestConfiguration) { - List mediaTypes = new ArrayList(); + List mediaTypes = new ArrayList<>(); // Configure this mapper to be used if HAL is not the default media type - if (!repositoryRestConfiguration().useHalAsDefaultJsonMediaType()) { + if (!repositoryRestConfiguration.useHalAsDefaultJsonMediaType()) { mediaTypes.add(MediaType.APPLICATION_JSON); } - int order = repositoryRestConfiguration().useHalAsDefaultJsonMediaType() ? Ordered.LOWEST_PRECEDENCE - 1 + int order = repositoryRestConfiguration.useHalAsDefaultJsonMediaType() ? Ordered.LOWEST_PRECEDENCE - 1 : Ordered.LOWEST_PRECEDENCE - 10; mediaTypes.addAll(Arrays.asList(RestMediaTypes.SCHEMA_JSON, // @@ -463,27 +570,28 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon // @Bean - public TypeConstrainedMappingJackson2HttpMessageConverter halJacksonHttpMessageConverter() { + public TypeConstrainedMappingJackson2HttpMessageConverter halJacksonHttpMessageConverter(LinkCollector linkCollector, + RepositoryRestConfiguration repositoryRestConfiguration) { - ArrayList mediaTypes = new ArrayList(); + ArrayList mediaTypes = new ArrayList<>(); mediaTypes.add(MediaTypes.HAL_JSON); // Enable returning HAL if application/json is asked if it's configured to be the default type - if (repositoryRestConfiguration().useHalAsDefaultJsonMediaType()) { + if (repositoryRestConfiguration.useHalAsDefaultJsonMediaType()) { mediaTypes.add(MediaType.APPLICATION_JSON); } - int order = repositoryRestConfiguration().useHalAsDefaultJsonMediaType() ? Ordered.LOWEST_PRECEDENCE - 10 + int order = repositoryRestConfiguration.useHalAsDefaultJsonMediaType() ? Ordered.LOWEST_PRECEDENCE - 10 : Ordered.LOWEST_PRECEDENCE - 1; TypeConstrainedMappingJackson2HttpMessageConverter converter = new ResourceSupportHttpMessageConverter(order); - converter.setObjectMapper(halObjectMapper()); + converter.setObjectMapper(halObjectMapper(linkCollector)); converter.setSupportedMediaTypes(mediaTypes); return converter; } - public ObjectMapper halObjectMapper() { + public ObjectMapper halObjectMapper(LinkCollector linkCollector) { LinkRelationProvider defaultedRelProvider = this.relProvider.orElseGet(EvoInflectorLinkRelationProvider::new); HalConfiguration halConfiguration = this.halConfiguration.orElseGet(HalConfiguration::new); @@ -492,7 +600,7 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon curieProvider.orElse(new DefaultCurieProvider(Collections.emptyMap())), resolver, halConfiguration); ObjectMapper mapper = basicObjectMapper(); - mapper.registerModule(persistentEntityJackson2Module()); + mapper.registerModule(persistentEntityJackson2Module(linkCollector)); mapper.registerModule(new Jackson2HalModule()); mapper.setHandlerInstantiator(instantiator); @@ -517,18 +625,24 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon * @return */ @Bean - public RequestMappingHandlerAdapter repositoryExporterHandlerAdapter() { + public RequestMappingHandlerAdapter repositoryExporterHandlerAdapter( + @Qualifier("defaultMessageConverters") List> defaultMessageConverters, + AlpsJsonHttpMessageConverter alpsJsonHttpMessageConverter, SelfLinkProvider selfLinkProvider, + PersistentEntityResourceHandlerMethodArgumentResolver persistentEntityArgumentResolver, + RootResourceInformationHandlerMethodArgumentResolver repoRequestArgumentResolver, + RepositoryRestConfiguration repositoryRestConfiguration) { // Forward conversion service to handler adapter ConfigurableWebBindingInitializer initializer = new ConfigurableWebBindingInitializer(); - initializer.setConversionService(defaultConversionService()); + initializer.setConversionService(defaultConversionService); - RepositoryRestHandlerAdapter handlerAdapter = new RepositoryRestHandlerAdapter(defaultMethodArgumentResolvers()); + RepositoryRestHandlerAdapter handlerAdapter = new RepositoryRestHandlerAdapter(defaultMethodArgumentResolvers( + selfLinkProvider, persistentEntityArgumentResolver, repoRequestArgumentResolver)); handlerAdapter.setWebBindingInitializer(initializer); - handlerAdapter.setMessageConverters(defaultMessageConverters()); + handlerAdapter.setMessageConverters(defaultMessageConverters); - if (repositoryRestConfiguration().getMetadataConfiguration().alpsEnabled()) { - handlerAdapter.setResponseBodyAdvice(Arrays.> asList(alpsJsonHttpMessageConverter())); + if (repositoryRestConfiguration.getMetadataConfiguration().alpsEnabled()) { + handlerAdapter.setResponseBodyAdvice(Arrays.asList(alpsJsonHttpMessageConverter)); } return handlerAdapter; @@ -543,23 +657,25 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon * @return */ @Bean - public AbstractHandlerMapping restHandlerMapping() { + public AbstractHandlerMapping restHandlerMapping(Repositories repositories, + RepositoryResourceMappings resourceMappings, Optional jpaHelper, + RepositoryRestConfiguration repositoryRestConfiguration, CorsConfigurationAware corsRestConfiguration) { - Map corsConfigurations = repositoryRestConfiguration().getCorsConfigurations(); + Map corsConfigurations = corsRestConfiguration.getCorsConfigurations(); - RepositoryRestHandlerMapping repositoryMapping = new RepositoryRestHandlerMapping(resourceMappings(), - repositoryRestConfiguration(), repositories()); - repositoryMapping.setJpaHelper(jpaHelper()); + RepositoryRestHandlerMapping repositoryMapping = new RepositoryRestHandlerMapping(resourceMappings, + repositoryRestConfiguration, repositories); + repositoryMapping.setJpaHelper(jpaHelper.orElse(null)); repositoryMapping.setApplicationContext(applicationContext); repositoryMapping.setCorsConfigurations(corsConfigurations); repositoryMapping.afterPropertiesSet(); - BasePathAwareHandlerMapping basePathMapping = new BasePathAwareHandlerMapping(repositoryRestConfiguration()); + BasePathAwareHandlerMapping basePathMapping = new BasePathAwareHandlerMapping(repositoryRestConfiguration); basePathMapping.setApplicationContext(applicationContext); basePathMapping.setCorsConfigurations(corsConfigurations); basePathMapping.afterPropertiesSet(); - List mappings = new ArrayList(); + List mappings = new ArrayList<>(); mappings.add(basePathMapping); mappings.add(repositoryMapping); @@ -572,12 +688,13 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon */ @Override public void configurePathMatch(PathMatchConfigurer configurer) { - restHandlerMapping().setPatternParser(configurer.getPatternParser()); + restHandlerMapping.get().setPatternParser(configurer.getPatternParser()); } @Bean - public RepositoryResourceMappings resourceMappings() { - return new RepositoryResourceMappings(repositories(), persistentEntities(), repositoryRestConfiguration()); + public RepositoryResourceMappings resourceMappings(Repositories repositories, PersistentEntities persistentEntities, + RepositoryRestConfiguration repositoryRestConfiguration) { + return new RepositoryResourceMappings(repositories, persistentEntities, repositoryRestConfiguration); } /** @@ -585,38 +702,30 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon * * @return */ - protected Module persistentEntityJackson2Module() { + protected Module persistentEntityJackson2Module(LinkCollector linkCollector) { - PersistentEntities entities = persistentEntities(); - ConversionService conversionService = defaultConversionService(); - - UriToEntityConverter uriToEntityConverter = uriToEntityConverter(conversionService); - RepositoryInvokerFactory repositoryInvokerFactory = repositoryInvokerFactory(conversionService); - - EmbeddedResourcesAssembler assembler = new EmbeddedResourcesAssembler(entities, associationLinks(), - excerptProjector()); + EmbeddedResourcesAssembler assembler = new EmbeddedResourcesAssembler(persistentEntities.get(), + associationLinks.get(), excerptProjector.get()); LookupObjectSerializer lookupObjectSerializer = new LookupObjectSerializer(PluginRegistry.of(getEntityLookups())); - return new PersistentEntityJackson2Module(associationLinks(), entities, uriToEntityConverter, linkCollector(), - repositoryInvokerFactory, lookupObjectSerializer, invoker.getObject(), assembler); + return new PersistentEntityJackson2Module(associationLinks.get(), persistentEntities.get(), + new UriToEntityConverter(persistentEntities.get(), repositoryInvokerFactory.get(), repositories.get()), + linkCollector, repositoryInvokerFactory.get(), lookupObjectSerializer, invoker.getObject(), assembler); } @Bean - protected LinkCollector linkCollector() { - return new LinkCollector(persistentEntities(), selfLinkProvider(), associationLinks()); - } - - protected UriToEntityConverter uriToEntityConverter(ConversionService conversionService) { - return new UriToEntityConverter(persistentEntities(), repositoryInvokerFactory(conversionService), repositories()); + protected LinkCollector linkCollector(PersistentEntities persistentEntities, SelfLinkProvider selfLinkProvider, + Associations associationLinks) { + return new LinkCollector(persistentEntities, selfLinkProvider, associationLinks); } @Bean - public ExcerptProjector excerptProjector() { + public ExcerptProjector excerptProjector(RepositoryResourceMappings resourceMappings) { SpelAwareProxyProjectionFactory projectionFactory = new SpelAwareProxyProjectionFactory(); projectionFactory.setBeanFactory(applicationContext); - return new DefaultExcerptProjector(projectionFactory, resourceMappings()); + return new DefaultExcerptProjector(projectionFactory, resourceMappings); } /* @@ -627,10 +736,11 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon public void extendHandlerExceptionResolvers(List exceptionResolvers) { ExceptionHandlerExceptionResolver er = new ExceptionHandlerExceptionResolver(); - er.setCustomArgumentResolvers(defaultMethodArgumentResolvers()); - er.setMessageConverters(defaultMessageConverters()); + er.setCustomArgumentResolvers(defaultMethodArgumentResolvers(selfLinkProvider.get(), + persistentEntityArgumentResolver.get(), repoRequestArgumentResolver.get())); + er.setMessageConverters(defaultMessageConverters); - configurerDelegate.configureExceptionHandlerExceptionResolver(er); + configurerDelegate.get().configureExceptionHandlerExceptionResolver(er); er.afterPropertiesSet(); @@ -643,34 +753,39 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon } @Bean - public RepositoryInvokerFactory repositoryInvokerFactory(@Qualifier ConversionService defaultConversionService) { - + @Qualifier + public RepositoryInvokerFactory repositoryInvokerFactory() { return new UnwrappingRepositoryInvokerFactory( - new DefaultRepositoryInvokerFactory(repositories(), defaultConversionService), getEntityLookups()); + new DefaultRepositoryInvokerFactory(repositories.get(), defaultConversionService), getEntityLookups()); } @Bean - public List> defaultMessageConverters() { + public List> defaultMessageConverters( + @Qualifier("jacksonHttpMessageConverter") TypeConstrainedMappingJackson2HttpMessageConverter jacksonHttpMessageConverter, + @Qualifier("halJacksonHttpMessageConverter") TypeConstrainedMappingJackson2HttpMessageConverter halJacksonHttpMessageConverter, + AlpsJsonHttpMessageConverter alpsJsonHttpMessageConverter, + UriListHttpMessageConverter uriListHttpMessageConverter, RepositoryRestConfigurerDelegate configurerDelegate, + RepositoryRestConfiguration repositoryRestConfiguration) { - List> messageConverters = new ArrayList>(); + List> messageConverters = new ArrayList<>(); - if (repositoryRestConfiguration().getMetadataConfiguration().alpsEnabled()) { - messageConverters.add(alpsJsonHttpMessageConverter()); + if (repositoryRestConfiguration.getMetadataConfiguration().alpsEnabled()) { + messageConverters.add(alpsJsonHttpMessageConverter); } - if (repositoryRestConfiguration().getDefaultMediaType().equals(MediaTypes.HAL_JSON)) { - messageConverters.add(halJacksonHttpMessageConverter()); - messageConverters.add(jacksonHttpMessageConverter()); + if (repositoryRestConfiguration.getDefaultMediaType().equals(MediaTypes.HAL_JSON)) { + messageConverters.add(halJacksonHttpMessageConverter); + messageConverters.add(jacksonHttpMessageConverter); } else { - messageConverters.add(jacksonHttpMessageConverter()); - messageConverters.add(halJacksonHttpMessageConverter()); + messageConverters.add(jacksonHttpMessageConverter); + messageConverters.add(halJacksonHttpMessageConverter); } MappingJackson2HttpMessageConverter fallbackJsonConverter = new MappingJackson2HttpMessageConverter(); fallbackJsonConverter.setObjectMapper(basicObjectMapper()); messageConverters.add(fallbackJsonConverter); - messageConverters.add(uriListHttpMessageConverter()); + messageConverters.add(uriListHttpMessageConverter); configurerDelegate.configureHttpMessageConverters(messageConverters); @@ -678,8 +793,9 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon } @Bean - public AlpsJsonHttpMessageConverter alpsJsonHttpMessageConverter() { - return new AlpsJsonHttpMessageConverter(alpsConverter()); + public AlpsJsonHttpMessageConverter alpsJsonHttpMessageConverter( + RootResourceInformationToAlpsDescriptorConverter alpsConverter) { + return new AlpsJsonHttpMessageConverter(alpsConverter); } /* @@ -691,10 +807,11 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon public HateoasPageableHandlerMethodArgumentResolver pageableResolver() { HateoasPageableHandlerMethodArgumentResolver resolver = super.pageableResolver(); - resolver.setPageParameterName(repositoryRestConfiguration().getPageParamName()); - resolver.setSizeParameterName(repositoryRestConfiguration().getLimitParamName()); - resolver.setFallbackPageable(PageRequest.of(0, repositoryRestConfiguration().getDefaultPageSize())); - resolver.setMaxPageSize(repositoryRestConfiguration().getMaxPageSize()); + + resolver.setPageParameterName(repositoryRestConfiguration.get().getPageParamName()); + resolver.setSizeParameterName(repositoryRestConfiguration.get().getLimitParamName()); + resolver.setFallbackPageable(PageRequest.of(0, repositoryRestConfiguration.get().getDefaultPageSize())); + resolver.setMaxPageSize(repositoryRestConfiguration.get().getMaxPageSize()); return resolver; } @@ -708,7 +825,7 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon public HateoasSortHandlerMethodArgumentResolver sortResolver() { HateoasSortHandlerMethodArgumentResolver resolver = super.sortResolver(); - resolver.setSortParameter(repositoryRestConfiguration().getSortParamName()); + resolver.setSortParameter(repositoryRestConfiguration.get().getSortParamName()); return resolver; } @@ -716,7 +833,7 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon @Bean public PluginRegistry> backendIdConverterRegistry() { - List converters = new ArrayList(idConverters.size()); + List converters = new ArrayList<>(idConverters.size()); converters.addAll(this.idConverters); converters.add(DefaultIdConverter.INSTANCE); @@ -724,64 +841,62 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon } @Bean - public AuditableBeanWrapperFactory auditableBeanWrapperFactory() { - return new MappingAuditableBeanWrapperFactory(persistentEntities()); + public AuditableBeanWrapperFactory auditableBeanWrapperFactory(PersistentEntities persistentEntities) { + return new MappingAuditableBeanWrapperFactory(persistentEntities); } @Bean - public HttpHeadersPreparer httpHeadersPreparer() { - return new HttpHeadersPreparer(auditableBeanWrapperFactory()); + public HttpHeadersPreparer httpHeadersPreparer(AuditableBeanWrapperFactory auditableBeanWrapperFactory) { + return new HttpHeadersPreparer(auditableBeanWrapperFactory); } @Bean - public SelfLinkProvider selfLinkProvider() { - return new DefaultSelfLinkProvider(persistentEntities(), entityLinks(), getEntityLookups()); + public SelfLinkProvider selfLinkProvider(PersistentEntities persistentEntities, RepositoryEntityLinks entityLinks) { + return new DefaultSelfLinkProvider(persistentEntities, entityLinks, getEntityLookups()); } @Bean - public Associations associationLinks() { - return new Associations(resourceMappings(), repositoryRestConfiguration()); + public Associations associationLinks(RepositoryResourceMappings resourceMappings, + RepositoryRestConfiguration repositoryRestConfiguration) { + return new Associations(resourceMappings, repositoryRestConfiguration); } protected List> getEntityLookups() { - List> lookups = new ArrayList>(); - lookups.addAll(repositoryRestConfiguration().getEntityLookups(repositories())); + List> lookups = new ArrayList<>(); + lookups.addAll(repositoryRestConfiguration.get().getEntityLookups(repositories.get())); lookups.addAll(this.lookups); return lookups; } - protected List defaultMethodArgumentResolvers() { + protected List defaultMethodArgumentResolvers(SelfLinkProvider selfLinkProvider, + PersistentEntityResourceHandlerMethodArgumentResolver persistentEntityArgumentResolver, + RootResourceInformationHandlerMethodArgumentResolver repoRequestArgumentResolver) { SpelAwareProxyProjectionFactory projectionFactory = new SpelAwareProxyProjectionFactory(); projectionFactory.setBeanFactory(applicationContext); projectionFactory.setBeanClassLoader(beanClassLoader); - PersistentEntityResourceAssemblerArgumentResolver peraResolver = new PersistentEntityResourceAssemblerArgumentResolver( - persistentEntities(), selfLinkProvider(), repositoryRestConfiguration().getProjectionConfiguration(), - projectionFactory, associationLinks()); - - PageableHandlerMethodArgumentResolver pageableResolver = pageableResolver(); - JacksonMappingAwareSortTranslator sortTranslator = new JacksonMappingAwareSortTranslator(objectMapper(), - repositories(), DomainClassResolver.of(repositories(), resourceMappings(), baseUri()), persistentEntities(), - associationLinks()); + repositories.get(), DomainClassResolver.of(repositories.get(), resourceMappings.get(), baseUri.get()), + persistentEntities.get(), associationLinks.get()); - HandlerMethodArgumentResolver sortResolver = new MappingAwareSortArgumentResolver(sortTranslator, sortResolver()); - HandlerMethodArgumentResolver jacksonPageableResolver = new MappingAwarePageableArgumentResolver(sortTranslator, - pageableResolver); - HandlerMethodArgumentResolver defaultedPageableResolver = new MappingAwareDefaultedPageableArgumentResolver( - sortTranslator, pageableResolver); - - return Arrays.asList(defaultedPageableResolver, jacksonPageableResolver, sortResolver, - serverHttpRequestMethodArgumentResolver(), repoRequestArgumentResolver(), persistentEntityArgumentResolver(), - resourceMetadataHandlerMethodArgumentResolver(), HttpMethodHandlerMethodArgumentResolver.INSTANCE, peraResolver, - backendIdHandlerMethodArgumentResolver(), eTagArgumentResolver()); + return Arrays.asList( // + new MappingAwareDefaultedPageableArgumentResolver(sortTranslator, pageableResolver.get()), // + new MappingAwarePageableArgumentResolver(sortTranslator, pageableResolver.get()), // + new MappingAwareSortArgumentResolver(sortTranslator, this.sortResolver.get()), // + serverHttpRequestMethodArgumentResolver.get(), // + repoRequestArgumentResolver, // + persistentEntityArgumentResolver, // + resourceMetadataHandlerMethodArgumentResolver.get(), // + HttpMethodHandlerMethodArgumentResolver.INSTANCE, // + new PersistentEntityResourceAssemblerArgumentResolver(persistentEntities.get(), selfLinkProvider, + repositoryRestConfiguration.get().getProjectionConfiguration(), projectionFactory, associationLinks.get()), // + backendIdHandlerMethodArgumentResolver.get(), // + eTagArgumentResolver.get()); } - @Autowired GeoModule geoModule; - protected ObjectMapper basicObjectMapper() { ObjectMapper mapper = this.objectMapper.getIfAvailable(); @@ -792,12 +907,12 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // Configure custom Modules - configurerDelegate.configureJacksonObjectMapper(objectMapper); + configurerDelegate.get().configureJacksonObjectMapper(objectMapper); objectMapper.registerModule(geoModule); - if (repositoryRestConfiguration().isEnableEnumTranslation()) { - objectMapper.registerModule(new JacksonSerializers(enumTranslator())); + if (repositoryRestConfiguration.get().isEnableEnumTranslation()) { + objectMapper.registerModule(new JacksonSerializers(enumTranslator.get())); } Jackson2DatatypeHelper.configureObjectMapper(objectMapper); @@ -806,7 +921,7 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon } @Bean - public EnumTranslator enumTranslator() { + public EnumTranslator enumTranslator(MessageResolver resolver) { return new EnumTranslator(resolver); } @@ -830,20 +945,17 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon // @Bean - public RootResourceInformationToAlpsDescriptorConverter alpsConverter() { + public RootResourceInformationToAlpsDescriptorConverter alpsConverter(Repositories repositories, + PersistentEntities persistentEntities, RepositoryEntityLinks entityLinks, EnumTranslator enumTranslator, + Associations associationLinks, RepositoryRestConfiguration repositoryRestConfiguration) { - Repositories repositories = repositories(); - PersistentEntities persistentEntities = persistentEntities(); - RepositoryEntityLinks entityLinks = entityLinks(); - RepositoryRestConfiguration config = repositoryRestConfiguration(); - - return new RootResourceInformationToAlpsDescriptorConverter(associationLinks(), repositories, persistentEntities, - entityLinks, resolver, config, objectMapper(), enumTranslator()); + return new RootResourceInformationToAlpsDescriptorConverter(associationLinks, repositories, persistentEntities, + entityLinks, resolver, repositoryRestConfiguration, objectMapper(), enumTranslator); } @Bean - public ProfileResourceProcessor profileResourceProcessor(RepositoryRestConfiguration config) { - return new ProfileResourceProcessor(config); + public ProfileResourceProcessor profileResourceProcessor(RepositoryRestConfiguration repositoryRestConfiguration) { + return new ProfileResourceProcessor(repositoryRestConfiguration); } // @@ -857,10 +969,8 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { - RepositoryRestConfiguration configuration = repositoryRestConfiguration(); - SpringFactoriesLoader.loadFactories(StaticResourceProvider.class, beanClassLoader) - .forEach(it -> it.customizeResources(registry, configuration)); + .forEach(it -> it.customizeResources(registry, repositoryRestConfiguration.get())); } private static class ResourceSupportHttpMessageConverter extends TypeConstrainedMappingJackson2HttpMessageConverter