Je travaille avec spring-boot sur un projet multi-modules (maven). Chaque module possède sa propre classe @Configuration. Fondamentalement, j'ai la disposition suivante
Module foo-embedded (s'exécute appelle simplement la méthode SpringApplication.run ()):
@Configuration
@EnableAutoConfiguration
@ComponentScan("de.foobar.rootpackage")
@Import({ApplicationConfig.class, RepositoryConfig.class, SecurityConfig.class})
public class FooApplication {
public static void main(String[] args) throws Exception {
SpringApplication.run(FooApplication.class, args);
}
}
Module foo-common (contient tous les beans et la configuration d'initialisation spring-data-jpa)
@Configuration
@EnableJpaRepositories
@EnableTransactionManagement(entityManagerFactoryRef="entityManagerFactory")
public class RepositoryConfig {
@Bean(destroyMethod = "shutdown")
public DataSource getDataSource() {
// returning a Hikari CP here
}
@Bean(name = "entityManagerFactory") // overriding spring boots default
public EntityManagerFactory getEntityManagerFactory() {
// returning a new LocalEntityManagerFactoryBean here
}
}
Module foo-security (contenant la configuration spring-securiy et les classes de domaine associées), qui a une dépendance maven sur foo-common
@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
// configuring HTTP security and defining my UserDetailsService Bean
}
Lorsque je démarre l'application à l'aide de la classe FooApplication, tout fonctionne comme prévu. Les UserDetailsServiceImpl mentionnés ci-dessus sont câblés automatiquement avec mon UserRepository qui est créé via l'annotation @EnableJpaRepositories.
Depuis que je veux écrire des tests d'intégration, j'ai ajouté un test clss à l'un de mes modules.
Module foo-media (contenant des éléments liés au domaine et des cas de test pour ce module)
@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {RepositoryConfig.class, SecurityConfig.class})
@WebAppConfiguration
@IntegrationTest
public class DirectoryIntegrationTest {
// my test code
}
Lorsque j'exécute le test, il semble que la SecurityConfiguration soit chargée avant le RepositoryConfig.class. Comme la configuration de sécurité a défini UserServiceImpl qui doit être câblé automatiquement, le test ne démarre pas avec un
NoSuchBeanDefinitionException telling me: No qualifying bean of type [com.foo.rootpackage.security.repository.UserRepository]
J'ai déjà essayé d'ajouter @DependsOn("UserRepository")
à la définition de bean de UserDetailsService
, me disant que spring ne peut pas trouver un bean de ce nom.
Tout conseil ou aide serait grandement apprécié! Merci d'avance!
---- MODIFIER (car on m'a demandé de fournir plus de code) ----
Pour les tests, je n'utilise pas le RepositoryConfig.class réel, mais j'ai un TestRepositoryConfig.class dans le module commun. Ressemblant à ceci
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactory", basePackages = "de.foobar.rootpackage")
public class TestRepositoryConfig extends RepositoryConfig {
@Bean
@Override
public DataSource getDataSource() {
// returning the ds for testing
}
}
J'ai donc pu résoudre ce problème. Comme il l'a souligné, cela n'avait rien à voir avec l'ordre de chargement des classes de configuration (ce qui était ma première pensée).
Comme vous pouvez le remarquer, la seule configuration qui avait un @ComponentScan
l'annotation était que FooApplication.class Spring n'était pas en mesure de trouver les référentiels, car il ne savait pas où chercher. Fournir l'attribut basePackages comme ceci:
@EnableJpaRepositories(basePackages = "de.foobar.rootpackage")
à TestRepositoryConfig.class a fait l'affaire ici.
Vous pouvez utiliser @Order
annotation sur vos classes de configuration pour définir l'ordre de chargement. Mais c'est étrange car Spring devrait résoudre le bon ordre - veuillez donc vérifier si votre propriété injecte UserRepository
dans UserDetailsService