2929import org .springframework .beans .factory .BeanFactoryUtils ;
3030import org .springframework .beans .factory .ObjectFactory ;
3131import org .springframework .beans .factory .ObjectProvider ;
32- import org .springframework .beans .factory .annotation .Autowired ;
3332import org .springframework .beans .factory .annotation .Qualifier ;
3433import org .springframework .context .ApplicationContext ;
3534import org .springframework .context .annotation .Bean ;
8887import org .springframework .data .rest .webmvc .support .RepositoryEntityLinks ;
8988import org .springframework .data .util .AnnotatedTypeScanner ;
9089import org .springframework .data .util .Lazy ;
90+ import org .springframework .data .util .StreamUtils ;
9191import org .springframework .data .web .HateoasPageableHandlerMethodArgumentResolver ;
9292import org .springframework .data .web .HateoasSortHandlerMethodArgumentResolver ;
9393import org .springframework .data .web .config .EnableSpringDataWebSupport ;
@@ -155,47 +155,43 @@ public class RepositoryRestMvcConfiguration extends HateoasAwareSpringDataWebCon
155155 private static final boolean IS_JPA_AVAILABLE = ClassUtils .isPresent ("javax.persistence.EntityManager" ,
156156 RepositoryRestMvcConfiguration .class .getClassLoader ());
157157
158- @ Autowired ApplicationContext applicationContext ;
158+ private final ApplicationContext applicationContext ;
159+ private final ConversionService defaultConversionService ;
159160
160- @ Autowired (required = false ) List <EntityLookup <?>> lookups = Collections .emptyList ();
161-
162- @ Autowired List <HttpMessageConverter <?>> defaultMessageConverters ;
163-
164- ObjectProvider <LinkRelationProvider > relProvider ;
165- ObjectProvider <CurieProvider > curieProvider ;
166- ObjectProvider <HalConfiguration > halConfiguration ;
167- ObjectProvider <ObjectMapper > objectMapper ;
168- ObjectProvider <RepresentationModelProcessorInvoker > invoker ;
169- ObjectProvider <MessageResolver > resolver ;
170- ObjectProvider <GeoModule > geoModule ;
171-
172- ConversionService defaultConversionService ;
161+ private final ObjectProvider <LinkRelationProvider > relProvider ;
162+ private final ObjectProvider <CurieProvider > curieProvider ;
163+ private final ObjectProvider <HalConfiguration > halConfiguration ;
164+ private final ObjectProvider <ObjectMapper > objectMapper ;
165+ private final ObjectProvider <RepresentationModelProcessorInvoker > invoker ;
166+ private final ObjectProvider <MessageResolver > resolver ;
167+ private final ObjectProvider <GeoModule > geoModule ;
168+ private final ObjectProvider <PathPatternParser > parser ;
173169
174170 private final Lazy <ObjectMapper > mapper ;
175- private final ObjectProvider <PathPatternParser > parser ;
171+ private final Lazy <? extends List <EntityLookup <?>>> lookups ;
172+ private final Lazy <? extends List <HttpMessageConverter <?>>> defaultMessageConverters ;
173+ private final Lazy <RepositoryRestConfigurerDelegate > configurerDelegate ;
174+ private final Lazy <SelfLinkProvider > selfLinkProvider ;
175+ private final Lazy <PersistentEntityResourceHandlerMethodArgumentResolver > persistentEntityArgumentResolver ;
176+ private final Lazy <RootResourceInformationHandlerMethodArgumentResolver > repoRequestArgumentResolver ;
177+ private final Lazy <BaseUri > baseUri ;
178+ private final Lazy <RepositoryResourceMappings > resourceMappings ;
179+ private final Lazy <Repositories > repositories ;
180+ private final Lazy <ResourceMetadataHandlerMethodArgumentResolver > resourceMetadataHandlerMethodArgumentResolver ;
181+ private final Lazy <ExcerptProjector > excerptProjector ;
182+ private final Lazy <PersistentEntities > persistentEntities ;
183+ private final Lazy <BackendIdHandlerMethodArgumentResolver > backendIdHandlerMethodArgumentResolver ;
184+ private final Lazy <Associations > associationLinks ;
185+ private final Lazy <EnumTranslator > enumTranslator ;
186+ private final Lazy <ServerHttpRequestMethodArgumentResolver > serverHttpRequestMethodArgumentResolver ;
187+ private final Lazy <ETagArgumentResolver > eTagArgumentResolver ;
188+ private final Lazy <RepositoryInvokerFactory > repositoryInvokerFactory ;
189+ private final Lazy <RepositoryRestConfiguration > repositoryRestConfiguration ;
190+ private final Lazy <HateoasPageableHandlerMethodArgumentResolver > pageableResolver ;
191+ private final Lazy <HateoasSortHandlerMethodArgumentResolver > sortResolver ;
176192
177193 private ClassLoader beanClassLoader ;
178194
179- private Lazy <RepositoryRestConfigurerDelegate > configurerDelegate ;
180- private Lazy <SelfLinkProvider > selfLinkProvider ;
181- private Lazy <PersistentEntityResourceHandlerMethodArgumentResolver > persistentEntityArgumentResolver ;
182- private Lazy <RootResourceInformationHandlerMethodArgumentResolver > repoRequestArgumentResolver ;
183- private Lazy <BaseUri > baseUri ;
184- private Lazy <RepositoryResourceMappings > resourceMappings ;
185- private Lazy <Repositories > repositories ;
186- private Lazy <ResourceMetadataHandlerMethodArgumentResolver > resourceMetadataHandlerMethodArgumentResolver ;
187- private Lazy <ExcerptProjector > excerptProjector ;
188- private Lazy <PersistentEntities > persistentEntities ;
189- private Lazy <BackendIdHandlerMethodArgumentResolver > backendIdHandlerMethodArgumentResolver ;
190- private Lazy <Associations > associationLinks ;
191- private Lazy <EnumTranslator > enumTranslator ;
192- private Lazy <ServerHttpRequestMethodArgumentResolver > serverHttpRequestMethodArgumentResolver ;
193- private Lazy <ETagArgumentResolver > eTagArgumentResolver ;
194- private Lazy <RepositoryInvokerFactory > repositoryInvokerFactory ;
195- private Lazy <RepositoryRestConfiguration > repositoryRestConfiguration ;
196- private Lazy <HateoasPageableHandlerMethodArgumentResolver > pageableResolver ;
197- private Lazy <HateoasSortHandlerMethodArgumentResolver > sortResolver ;
198-
199195 public RepositoryRestMvcConfiguration ( //
200196 ApplicationContext context , //
201197 @ Qualifier ("mvcConversionService" ) ObjectFactory <ConversionService > conversionService , //
@@ -210,6 +206,7 @@ public RepositoryRestMvcConfiguration( //
210206
211207 super (context , conversionService );
212208
209+ this .applicationContext = context ;
213210 this .relProvider = relProvider ;
214211 this .curieProvider = curieProvider ;
215212 this .halConfiguration = halConfiguration ;
@@ -218,6 +215,7 @@ public RepositoryRestMvcConfiguration( //
218215 this .resolver = resolver ;
219216 this .geoModule = geoModule ;
220217 this .parser = parser ;
218+ this .defaultConversionService = new DefaultFormattingConversionService ();
221219
222220 this .mapper = Lazy .of (() -> {
223221
@@ -253,11 +251,10 @@ public RepositoryRestMvcConfiguration( //
253251 this .serverHttpRequestMethodArgumentResolver = Lazy
254252 .of (() -> context .getBean (ServerHttpRequestMethodArgumentResolver .class ));
255253 this .eTagArgumentResolver = Lazy .of (() -> context .getBean (ETagArgumentResolver .class ));
254+
256255 this .repositoryInvokerFactory = Lazy .of (() -> new UnwrappingRepositoryInvokerFactory (
257256 new DefaultRepositoryInvokerFactory (repositories .get (), defaultConversionService ), getEntityLookups ()));
258257
259- this .defaultConversionService = new DefaultFormattingConversionService ();
260-
261258 this .configurerDelegate = Lazy .of (() -> {
262259
263260 return new RepositoryRestConfigurerDelegate (context .getBeanProvider (RepositoryRestConfigurer .class )
@@ -268,6 +265,11 @@ public RepositoryRestMvcConfiguration( //
268265 this .repositoryRestConfiguration = Lazy .of (() -> context .getBean (RepositoryRestConfiguration .class ));
269266 this .pageableResolver = Lazy .of (() -> context .getBean (HateoasPageableHandlerMethodArgumentResolver .class ));
270267 this .sortResolver = Lazy .of (() -> context .getBean (HateoasSortHandlerMethodArgumentResolver .class ));
268+
269+ // Resolution via ResolvableType needed to make the wildcard assignment work
270+
271+ this .lookups = beansOfType (context , EntityLookup .class );
272+ this .defaultMessageConverters = beansOfType (context , HttpMessageConverter .class );
271273 }
272274
273275 /*
@@ -747,7 +749,7 @@ public void extendHandlerExceptionResolvers(List<HandlerExceptionResolver> excep
747749 ExceptionHandlerExceptionResolver er = new ExceptionHandlerExceptionResolver ();
748750 er .setCustomArgumentResolvers (defaultMethodArgumentResolvers (selfLinkProvider .get (),
749751 persistentEntityArgumentResolver .get (), repoRequestArgumentResolver .get ()));
750- er .setMessageConverters (defaultMessageConverters );
752+ er .setMessageConverters (defaultMessageConverters . get () );
751753
752754 configurerDelegate .get ().configureExceptionHandlerExceptionResolver (er );
753755
@@ -879,7 +881,7 @@ protected List<EntityLookup<?>> getEntityLookups() {
879881
880882 List <EntityLookup <?>> lookups = new ArrayList <>();
881883 lookups .addAll (repositoryRestConfiguration .get ().getEntityLookups (repositories .get ()));
882- lookups .addAll (this .lookups );
884+ lookups .addAll (this .lookups . get () );
883885
884886 return lookups ;
885887 }
@@ -990,6 +992,23 @@ public void addResourceHandlers(ResourceHandlerRegistry registry) {
990992 .forEach (it -> it .customizeResources (registry , repositoryRestConfiguration .get ()));
991993 }
992994
995+ /**
996+ * Helper to be able to obtain a {@link List} of generic types. Otherwise the assignment from {@code Foo} to
997+ * {@code Foo<?>} doesn't work.
998+ *
999+ * @param <S>
1000+ * @param context
1001+ * @param type
1002+ * @return
1003+ */
1004+ @ SuppressWarnings ("unchecked" )
1005+ private static <S > Lazy <List <S >> beansOfType (ApplicationContext context , Class <?> type ) {
1006+
1007+ return Lazy .of (() -> (List <S >) context .getBeanProvider (type )
1008+ .orderedStream ()
1009+ .collect (StreamUtils .toUnmodifiableList ()));
1010+ }
1011+
9931012 private static class ResourceSupportHttpMessageConverter extends TypeConstrainedMappingJackson2HttpMessageConverter
9941013 implements Ordered {
9951014
0 commit comments