Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to enforce loading order of spring configuration classes?

Tags:

I'm working with spring-boot on a multi module project (maven). Each module has it's own @Configuration class. Basically I do have the following layout

Module foo-embedded (runs just calls the SpringApplication.run()) method:

@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 (contains all beans and spring-data-jpa initialization config)

@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 (containing spring-securiy configuration and related domain classes), which has a maven dependency on foo-common

@Configuration
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    // configuring HTTP security and defining my UserDetailsService Bean
}

When I start the application using the FooApplication class, everything works as expected. The above mentioned UserDetailsServiceImpl get's autowired with my UserRepository which is being created through the @EnableJpaRepositories annotation.

Since I want to write some integration tests I've added a test clss to one of my modules.

Module foo-media (containing some domain related stuff plus test cases for that module)

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = {RepositoryConfig.class, SecurityConfig.class})
@WebAppConfiguration
@IntegrationTest
public class DirectoryIntegrationTest {
    // my test code
}

When I run the test it seems that the SecurityConfiguration get's loaded before the RepositoryConfig.class does. Since the security config defined the UserServiceImpl which must be autowired, the test fails to start with a

NoSuchBeanDefinitionException telling me: No qualifying bean of type [com.foo.rootpackage.security.repository.UserRepository]

I already tried to add @DependsOn("UserRepository") at the bean definition of UserDetailsService, telling me that spring can't find a bean by that name.

Any hints or help would be greatly appreciated! Thanks in advance!

---- EDIT (since I was asked to provide more code) ----

For testing I do not use the actual RepositoryConfig.class, but have a TestRepositoryConfig.class in the common module. Looking like this

@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(entityManagerFactoryRef = "entityManagerFactory", basePackages = "de.foobar.rootpackage")
public class TestRepositoryConfig extends RepositoryConfig {

    @Bean
    @Override
    public DataSource getDataSource() {
        // returning the ds for testing
    }
}
like image 522
Markus Avatar asked Jun 18 '14 13:06

Markus


People also ask

What is @order annotation in Spring?

The @Order annotation defines the sorting order of an annotated component or bean. It has an optional value argument which determines the order of the component; the default value is Ordered. LOWEST_PRECEDENCE. This marks that the component has the lowest priority among all other ordered components.

What is @order ordered Highest_precedence?

@Order annotation has value attribute, it is used to define order of component or bean, and which is optional. The default value is Ordered. LOWEST_PRECEDENCE , indicating lowest priority. Similarly, Ordered. HIGHEST_PRECEDENCE indicates highest priority among components.


1 Answers

You can use @Order annotation on your configuration classes to define load ordering. But it's strange because Spring should resolve proper order - so please check if you property inject UserRepository in UserDetailsService

like image 131
Jakub Kubrynski Avatar answered Oct 08 '22 15:10

Jakub Kubrynski